一、准备工作
- 下载
vscode
,新建一个html
文件,ctrl+shift+p
打开命令面板,切换语言为html
- 在
<head>
中添加VUE
的CDN
地址<script src="https://unpkg.com/vue@next"></script>
,引入vue
库,我们就可以编写vue
代码了。 - 编写完
html
文件,可以直接通过option+b
用默认浏览器打开html
二、第一个VUE应用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello world</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
Vue.createApp({ //创建一个VUE实例
data() {
return {
count: 1 //定义数据,面向数据编程
}
},
mounted() {
console.log('mounted') //页面加载完成/vue元素挂载完成自动执行
setInterval(()=> { //写个定时器。 箭头函数最直观的三个特点:不需要 function 关键字来创建函数,省略 return 关键字,继承当前上下文的 this 关键字
this.count+=1; //执行内容 this.count=this.$data.count
},1000) //每隔一秒执行一次
},
template: '<div>计数:{{count}}</div>' //模版,作为挂载在元素上的展示内容。eg:<div id="root"><div>hello world</div></div>
}).mount('#root') //在id=root的dom元素上使用vue(把template里的元素挂载在id=root的元素上)
</script>
</html>
补充:
- Vue中的options
const vm = new Vue(options)
options的五类属性:
1)数据:data、 props、 propsData、 computed、methods、 Watch
2)DOM: el、 template、 render、 renderError
3)生命周期钩子: beforeCreate、 created、beforeMount、 mounted、 beforeUpdate、updated、 activated、 deactivated、 beforeDestroy、 destroyed、errorCaptured
4)资源: directives、 filters、 components
5)组合: parent, mixins、 extends、 provide、 inject- data
data(){ }通过一个函数返回一个对象,确保组件之间相互独立
因为如果采用Object(data:{count:1}),则相当于创建的时候采用同一个对象,当在某一个组件更改则其余的也会受到影响
使用函数会形成一个闭包的环境,保证每一个组件都拥有独立的数据
三、循环和双向绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello world</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
Vue.createApp({
data() {
return {
//list: ['hello','word','dell','lee']
list: [],
inputValue:''
}
},
methods:{
handleAddItem(){
this.list.push(this.inputValue);
this.inputValue=''; //清空输入框
}
},
template: `
<input v-model='inputValue'></input>
<button v-on:click="handleAddItem">增加</button>
<ul>
<li v-for="(item,idex) of list">{{item}}---{{idex}}</li>
</ul>
`
}).mount('#root');
</script>
</html>
组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello world</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app= Vue.createApp({
data() {
return {
//list: ['hello','word','dell','lee']
list: [],
inputValue:''
}
},
methods:{
handleAddItem(){
this.list.push(this.inputValue);
this.inputValue=''; //清空输入框
}
},
template: `
<input v-model="inputValue"/>
<button
v-on:click="handleAddItem"
v-bind:title="inputValue"
>
增加</button>
<ul>
<!--<li v-for="(item,idex) of list">{{item}}---{{idex}}</li>-->
<todo-item v-for="item of list" v-bind:content='item'/>
`
});
app.component('todo-item',{
props:['content'],
template: '<li>{{content}}</li>'
})
app.mount('#root');
</script>
</html>
四、vue中的应用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello world</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
//createApp表示创建一个VUE应用,存储到app变量中
//传入的参数表示,这个应用的最外层组件,应该如何展示
//mvvm设计模式,m - model数据 v - view视图,vm - viewModel视图数据连接层
const app= Vue.createApp({
data(){
return{
message:'hello world' //m - model数据
}
},
template: '<div>{{message}}</div>' //v - view视图
});
//vm代表的就是 vue应用的根组件
const vm=app.mount('#root'); //vm - viewModel视图数据连接层
</script>
</html>
五、vue中的生命周期函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello world</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
//生命周期函数:在某时刻会自动执行的函数
const app= Vue.createApp({
data(){
return{
message:'hello world'
}
},
beforeCreate() {
console.log('beforeCreate') //在实例生成之前会自动执行的函数
},
created() {
console.log('created') //在实例生成之后会自动执行的函数
},
beforeMount() {
console.log('beforeMount') //在组件内容被渲染到页面之前立即自动执行的函数(模版已经被编译成函数之后)
},
mounted() {
console.log('mounted') //在组件内容被渲染到页面之后立即自动执行的函数
console.log(document.getElementById('root').innerHTML) //可以获取dom元素
},
beforeUpdate() {
console.log('beforeUpdate') //当data中的数据变化时会自动执行的函数
},
updated() {
console.log('updated') //当data中的数据发生变化,同时页面完成更新后,会自动执行的函数
},
beforeUnMount(){
console.log('beforeUnMount') //当vue应用失效/销毁时,自动执行的函数
},
unmounted(){
console.log('unmounted') //当vue应用失效/销毁时,切dom完全销毁之后,自动执行的函数
},
methods: {
handleItemClick(){
alert("click") //需手动点击执行
}
},
template: '<div v-on:click="handleItemClick">{{message}}</div>'
});
const vm=app.mount('#root');
</script>
</html>
六、常用模版语法
<body>
<div id="root"></div>
</body>
<script>
const app= Vue.createApp({
data(){
return{
message:'<strong>hello world</strong>',
title:'hello',
disabled: true,
name: 'world',
show: false
}
},
template: `
<div v-bind:title="title" v-html="message"></div>
<input v-bind:disabled="disabled"/>
<div>{{'a'+'b'}}</div>
<div>{{Math.max(1,2)}}</div>
<div v-once>{{name}}</div>
<div v-if='show'>show</div>
`
});
const vm=app.mount('#root');
</script>
</html>
<script>
const app= Vue.createApp({
data(){
return{
message:'hello world',
name:'title',
event:'click'
}
},
methods: {
handleClick(){
alert('click')
},
handFormOnChange(e){
e.preventDefault();
}
},
template: `
<div v-on:click="handleClick" v-bind:title="message">hello</div>
<div @click="handleClick" :title="message">world</div>
<div @click="handleClick" :[name]="message">aaa</div>
<div @[event]="handleClick" :[name]="message">bbb</div>
<form action='https://www.baidu.com/'>
<button type='submit'>提交</button>
</form>
<form action='https://www.baidu.com/' @click="handFormOnChange">
<button type='submit'>提交不跳转</button>
</form>
<form action='https://www.baidu.com/' @click.prevent="handleClick">
<button type='submit'>提交不跳转</button>
</form>
`
});
const vm=app.mount('#root');
</script>
<script>
const app= Vue.createApp({
data(){
return{
message:'hello world',
count:10,
price:5
}
},
methods: {
testMethods(){
return Date.now(); //只要页面重新渲染,就会重新计算
},
strFormate(str){
return str.toUpperCase();
}
},
computed: {
testComputed(){
return Date.now(); //只有计算属性依赖的内容发生变化时,才会重新计算
},
totalInComputed(){
return this.count * this.price
}
},
template: `
<div>{{strFormate(message)}}</div>
<div>{{count * price}}</div>
<div>{{totalInComputed}}</div>
<div>{{testComputed}}</div>
<div>{{testMethods()}}</div>
`
});
const vm=app.mount('#root');
</script>
侦听器
<script>
const app= Vue.createApp({
data(){
return{
message: 2
}
},
watch: { //message改变触发,异步操作
message(current,prev){
setTimeout(()=>{
console.log(`message is changed. the current value is ${current}.the prev is ${prev}`)
},3000)
},
},
template: `
<div>{{message}}</div>
`
});
const vm=app.mount('#root');
</script>
循环
<script>
const app= Vue.createApp({
data(){
return{
listObject: {
name: 'zhangsan',
age: '18',
mail: '532979776@qq.com'
},
listArray: ['哈哈哈','呵呵呵']
}
},
methods: {
handleAddBtnClick(){
// 1. 改变数组
this.listArray.push('new hello') //添加
//this.listArray.pop('new hello') 删除
//this.listArray.shift() 往数组头部开始删
//this.listArray.unshift() 往数组头部开始加
// 2. 直接替换数组
// this.listArray=['bye','fell']
this.listArray=['bye','fell'].filter(itemInList=> itemInList==='fell')
// 3.直接更新数组的内容
this.listArray[1]='aa'
//直接添加对象的属性,也能展示
this.listObject.sex='male'
}
},
template: `
<div>
<template v-for="(value,key,idex) in listObject" :key="idex">
<div v-if="value !=='zhangsan'">
{{value}}--{{key}}--{{idex}}
</div>
</template><!--占位符,不渲染标签-->
<div v-for="(item,idex) in listArray" :key="idex">
{{item}}--{{idex}}
</div>
<div v-for="item in 10">
{{item}} <!--1 2 3 4 5 6 7 8 9 10-->
</div>
<Button @click='handleAddBtnClick'>新增</Button>
</div>
`
});
const vm=app.mount('#root');
</script>
事件
<script>
const app= Vue.createApp({
data(){
return{
count:0,
count1:0
}
},
methods: {
handleAddBtnClick(num,event){
this.count += num
console.log(`原生事件:${event.target}`)
},
handleAddBtnClick1(){
alert('click button')
},
handleAddBtnClick2(){
alert('click div')
},
handleAddBtnClick3(){
alert('click once')
}
},
template: `
<div>
{{count}}
<button @click='handleAddBtnClick(2,$event)'>增加</button>
</div>
<div>
{{count1}}
<button @click='this.count1 += 1'>增加</button>
</div>
<div>
{{count1}}
<button @click='handleAddBtnClick(3,$event),handleAddBtnClick1()'>多个方法</button>
</div>
<div @click.self='handleAddBtnClick2'>
<div>点我试试</div>
<div @click.once='handleAddBtnClick3'>我只能被你点一次</div>
<button @click.stop='handleAddBtnClick1'>停止冒泡</button></button>
</div>
`
});
const vm=app.mount('#root');
</script>
<script>
const app= Vue.createApp({
data(){
return{
count:0,
count1:0
}
},
methods: {
handleClick(){
console.log('按回车键了')
},
handleClick1(){
console.log('按删除键了')
},
handleClick2(){
console.log('单独按住ctrl键')
}
},
template: `
<input @keydown.enter='handleClick'/>
<input @keydown.delete='handleClick1'/>
<input @click.ctrl.exact='handleClick2'/>
`
});
const vm=app.mount('#root');
</script>
双向绑定
<script>
const app= Vue.createApp({
data(){
return{
choose:[],
message:[
{text:'好',value:'A'},
{text:'中',value:'B'},
{text:'差',value:'C'}
]
}
},
template: `
<div>
{{choose}}
<select v-model='choose' multiple>
<option v-for='item in message' :value='item.value'>{{item.text}}</option>
</select>
</div>
`
});
const vm=app.mount('#root');
</script>
<script>
const app= Vue.createApp({
data(){
return{
message:'',
second:0,
third:''
}
},
template: `
<div>
{{message}}
<input v-model.lazy='message' />
{{second}}
{{typeof second}}
<input v-model.number='second' />
{{third}}
<input v-model.trim='third' />
</div>
`
});
const vm=app.mount('#root');
</script>
组件
<script>
const app= Vue.createApp({
template: `
<div>
<hello/>
<world/>
</hello>
`
});
app.component('hello',{
template:`<div>hello</div>`
})
app.component('world',{
template:`<div>world</div>`
})
const vm=app.mount('#root');
</script>
<script>
const app= Vue.createApp({
template:`
<div>
<counter/>
<counter/>
<counter-parent/>
</hello>
`
});
app.component('counter-parent',{
template:`<counter/>`
})
app.component('counter',{
data() {
return {
count:0
}
},
template:`<div @click='count+=1'>{{count}}</div>`
})
const vm=app.mount('#root');
</script>
<script>
const MyCounter={
data() {
return {
count:0
}
},
template: `<div @click='count+=1'>{{count}}</div>`
}
const app= Vue.createApp({
components: {
'my-counter':MyCounter
},
template:`
<div>
<my-counter/>
</div>
`
});
const vm=app.mount('#root');
</script>
<script>
const MyCounter={
data() {
return {
count:0
}
},
template: `<div @click='count+=1'>{{count}}</div>`
}
const app= Vue.createApp({
data(){
return {
num:123,
fun: ()=>{
alert("parmater")
}
}
},
components: {
'my-counter':MyCounter
},
template:`
<div>
<my-counter/>
<test content='parmater'/>
<test1 :content1='num'/>
<test2 content2='myaaa'/>
<test3 :content3='fun'/>
<test3/>
</div>
`
});
app.component('test',{
props: ['content'],
template: `
<div>{{content}}</div>
<div>{{typeof content}}</div>
`
});
app.component('test1',{
props: ['content1'],
template: `
<div>{{content1}}</div>
<div>{{typeof content1}}</div>
`
});
app.component('test2',{
props: {
content2: String
},
template: `
<div>{{content2}}</div>
<div>{{typeof content2}}</div>
`
});
app.component('test3',{
props: {
content3: {
type: Function,
//required: true,
default: () => {
alert('default value')
}
}
},
methods: {
handlerClick(){
alert("click")
this.content3()
}
},
template: `<div @click="handlerClick">点我</div>`
});
const vm=app.mount('#root');
</script>
<script>
const app= Vue.createApp({
data(){
return {
params:{
a1:'h',
a2:'i'
},
pp1:'w',
pp2:'c'
}
},
template:`
<div>
<test v-bind='params'/>
<test :a1='pp1' :a2='pp2'/>
</div>
`
});
app.component('test',{
props: ['a1','a2'],
template: `
<div>{{a1}}</div>
<div>{{a2}}</div>
`
});
const vm=app.mount('#root');
</script>
<script>
const app= Vue.createApp({
template:`
<div>
<test p1='a' p2='b' a1='hello world'/>
</div>
`
});
app.component('test',{
//inheritAttrs:false,
props: ['a1'],
template: `
<div v-bind='$attrs'>{{a1}}</div>
<div :msg='$attrs.p1'>{{a1}}</div>
<div :msg1='$attrs.p2'>{{a1}}</div>
`
});
const vm=app.mount('#root');
</script>
<script>
const app= Vue.createApp({
data() {
return {
count:0
}
},
methods: {
handlerAddOne(){
this.count +=1
}
},
template:`
<div>
<test :count='count' @add-one-num='handlerAddOne'/>
</div>
`
});
app.component('test',{
props: ['count'],
methods: {
addOne(){
// this.count+=1
this.$emit('addOneNum')
}
},
template: `
<div @click='addOne'>{{count}}</div>
`
});
const vm=app.mount('#root');
</script>
<script>
const app= Vue.createApp({
data() {
return {
txt:'div提交'
}
},
template:`
<myform>
<button>提交</button>
<inner-dom></inner-dom>
</myform>
<myform1>
</myform1>
<layout>
<template v-slot:headerr>
<div>header</div>
</template>
<template v-slot:footerr>
<div>footer</div>
</template>
</layout>
`
});
app.component('innerDom',{
template: `<div>inner div component</div>`
})
app.component('myform',{
methods: {
handlerClick(){
alert('hello world')
}
},
template: `
<div>
<input/>
<span @click='handlerClick'>
<slot></slot>
</span>
</div>
`
});
app.component('myform1',{
methods: {
handlerClick(){
alert('hello world')
}
},
template: `
<div>
<input/>
<span @click='handlerClick'>
<slot>default value</slot>
</span>
</div>
`
});
app.component('layout',{
template: `
<div>
<slot name="headerr"></slot>
<div>body</div>
<slot name="footerr"></slot>
</div>
`
});
const vm=app.mount('#root');
</script>
<script>
const app= Vue.createApp({
data() {
return {
currtentItem:''
}
},
methods: {
handlerClick(){
if(this.currtentItem ==='go-component'){
this.currtentItem='back-component'
}else{
this.currtentItem='go-component'
}
}
},
template:`
<keep-alive>
<component :is="currtentItem"></component>
</keep-alive>
<button @click='handlerClick'>切换</button>
`
});
app.component('go-component',{
template: `<div>我走了</div>`
})
app.component('back-component',{
template: `<div>我回来了</div>`
})
const vm=app.mount('#root');
</script>
<script>
const syncComponent = {
template: `<div>我是同步的,最先展示</div>`
}
const app= Vue.createApp({
components: {
syncComponent: syncComponent
},
template:`
<syncComponent/>
<asyncComponent/>
`
});
app.component('asyncComponent',Vue.defineAsyncComponent(()=>{
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve({
template: `<div>我是异步的,后面展示</div>`
})
},4000)
})
}))
const vm=app.mount('#root');
</script>
mixin
<script>
const myMixin={
data(){
return{
num:2
}
},
methods: {
handleClick(){
console.log("mixin click")
}
},
created() {
console.log('mixin created')
}
}
const app= Vue.createApp({
data() {
return {
// num:1
}
},
mixins:[myMixin],
created() {
console.log('mian created')
},
methods:{
// handleClick(){
// console.log("main click")
//}
},
template:`
<div>
<div @click='handleClick'>{{num}}</div>
</div>
`
});
const vm=app.mount('#root');
</script>
自定义指令
<script>
const directives = {
focus: {
mounted(el) {
el.focus();
},
}
}
const app= Vue.createApp({
// mounted() {
// this.$refs.inputEl.focus();
// },
directives:directives,
template:`
<div>
<!--<input ref='inputEl'/>-->
<!--<input v-focus/>-->
<input v-focus/>
</div>
`
});
// app.directive('focus',{
// mounted(el){
// el.focus();
// }
// })
const vm=app.mount('#root');
</script>
<script>
const app= Vue.createApp({
data() {
return {
num:'100px'
}
},
template:`
<div>
<div v-pos='num' class="top">
<input/>
</div>
<!-- <div v-poss:left='num' class="top">
<input/>
</div> -->
</div>
`
});
app.directive('pos',{
mounted(el,binding) {
el.style.top=binding.value
},
updated(el,binding) {
el.style.top=binding.value
}
})
// app.directive('pos',(el,binding)=>{
// mounted(el,binding) {
// el.style[binding.arg]=binding.value
// }
// })
const vm=app.mount('#root');
</script>
插件
<script>
const myPlugin={
install(app,options){
console.log(app,options)
app.provide('myKey','lalalala')
app.config.globalProperties.$sayHello='hello world'
}
}
const app= Vue.createApp({
template:`
<my-component/>
`
});
app.component('my-component',{
inject:['myKey'],
mounted() {
console.log(this.$sayHello)
},
template: `<div>{{myKey}}</div>`
})
app.use(myPlugin,{name:'artka'})
const vm=app.mount('#root');
</script>
setup 函数
<script>
const app= Vue.createApp({
template:`
<div @click='handleClick'>{{name}}</div>
` ,
methods: {
test(){
console.log(this.$options.setup())
}
},
mounted() {
this.test();
},
setup(props,context) {
return{
name: 'dell',
handleClick:()=>{
alert('setup click')
}
}
}
});
const vm=app.mount('#root');
</script>
响应式引用 ref reactive toRef toRefs
<script>
const app= Vue.createApp({
template:`
<div>{{name}}</div>
<div>{{say}}</div>
<div>{{age}}</div>
` ,
setup(props,context) {
const{ref} = Vue
let name=ref('dell')
setTimeout(()=>{
name.value='lee'
},2000)
const {reactive} =Vue
const name1=reactive({say:'hen'})
setTimeout(()=>{
name1.say='ha'
},2000)
// const{say}=name1
const {toRefs} =Vue
const{say}=toRefs(name1)
const {toRef} =Vue
const data=reactive({key:'ya'})
const age=toRef(data,'age')
setTimeout(()=>{
age.value='18'
},2000)
return {name, say,age}
}
});
const vm=app.mount('#root');
</script>
<script>
const app= Vue.createApp({
setup(props) {
const {ref,reactive} = Vue;
const inputValue=ref('sdf');
const list=reactive([]);
const handlerChange=(e)=>{
inputValue.value=e.target.value
}
const submit=()=>{
list.push(inputValue.value)
}
return {
list,
submit,
inputValue,
handlerChange
}
},
template:`
<div>
<div>
<input :value='inputValue' @input='handlerChange'/>
<button @click='submit'>提交</button>
</div>
<ul>
<li v-for='item in list'>{{item}}</li>
</ul>
</div>
`
});
const vm=app.mount('#root');
</script>
<script>
const opList=()=>{
const {reactive} = Vue;
const list=reactive([]);
const submit=(item)=>{
list.push(item)
}
return {list,submit}
}
const opInput=()=>{
const {ref} = Vue;
const inputValue=ref('');
const handlerChange=(e)=>{
inputValue.value=e.target.value
}
return {inputValue,handlerChange}
}
const app= Vue.createApp({
setup(props) {
const {list,submit} =opList();
const {inputValue,handlerChange} = opInput();
return {
list,
submit,
inputValue,
handlerChange
}
},
template:`
<div>
<div>
<input :value='inputValue' @input='handlerChange'/>
<button @click='()=>submit(inputValue )'>提交</button>
</div>
<ul>
<li v-for='item in list'>{{item}}</li>
</ul>
</div>
`
});
const vm=app.mount('#root');
</script>
<script>
const app= Vue.createApp({
setup() {
const {ref,computed} =Vue
const count=ref(0)
const handleClick=()=>{
count.value +=1
}
const addFive=computed(()=>{
return count.value +5
})
let addTen=computed({
get: () => {
return count.value +10
},
set: () => {
count.value = 1000
}
})
setTimeout(()=>{
addTen.value=11
},3000)
return {handleClick,count,addFive,addTen}
},
template:`
<div @click='handleClick'>
{{count}}
</div>
<div>
{{addFive}}
</div>
<div>
{{addTen}}
</div>
`
});
const vm=app.mount('#root');
</script>
<script>
const app= Vue.createApp({
setup() {
const {watch,reactive,toRefs,watchEffect} =Vue
const nameObj=reactive({name:'zhangsan',engname:'lisi'})
const {name,engname} = toRefs(nameObj)
watch(()=>[nameObj.name,engname] ,([cur,pre],[en,ep])=>{
console.log(cur,pre,en,ep)
})
watchEffect(()=>{
console.log(engname)
setTimeout(()=>{
stop();
},5000)
})
return {name,engname}
},
template:`
<div>
<input v-model='name'/>
<div>
{{name}}
</div>
<input v-model='engname'/>
<div>
{{engname}}
</div>
</div>
`
});
const vm=app.mount('#root');
</script>