1. Vue核心(一)
1.1 模板语法
-
插值语法
功能:用于解析标签体的内容
写法:{{xxx}}, xxx是
js
表达式,且可以直接读取到data
中的所有属性 -
指令语法:
功能:用于解析标签,(包括标签属性,标签体内容,绑定事件…)
形式都是
v-???
v-band
<a v-bind:href="url">baidu</a>
v-band
相当于把后面引号内的属性当作 js
表达式,可以简写为 :
1.2 数据绑定
Vue中有2中数据绑定的方式:
- 单向绑定
v-bind
: 数据只能从data
流向页面 - 双向绑定
v-model
: 数据不仅能从data
流向页面,还可以从页面流向data
- 双向绑定一般都应用在表单类元素上
v-model:value
可以简写为v-model
<!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>初识Vue</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root"><div>单向数据绑定:<input type="text" :value="data1"></div><div>双向数据绑定:<input type="text" v-model:value="data1"></div></div><script type="text/javascript">Vue.config.productionTip = false // 阻止 vue 启动时生成生产提示const x = new Vue({el: '#root', // el 用于指定当前 Vue 实例为哪个容器服务,值通常为css选择器字符串data: { // data中用于存储数据,数据供el所指定的容器去使用,值我们暂定先写成一个对象data1: '中国',}})</script>
</body>
</html>
v-model
只能用在表单,输入类元素中
简写
<div>单向数据绑定:<input type="text" :value="data1">
</div>
<div>双向数据绑定:<input type="text" v-model="data1">
</div>
1.3 el 与 data 两种写法
el
Vue.config.productionTip = false // 阻止 vue 启动时生成生产提示
const x = new Vue({// el: '#root', // 方式一data: { // data中用于存储数据,数据供el所指定的容器去使用,值我们暂定先写成一个对象data1: '中国',}
})setTimeout(() => {x.$mount('#root') // 方式二
}, 1000);
data
对象式
data:{data1:'xxxx'
}
函数式
data:function(){return{data1:'xfdsaf'}
}data(){return{data1:'fdsfa'}
}
一个重要原则:
由 Vue
管理的函数,一定不要写箭头函数,一旦写了箭头函数,this
就不再是 Vue
的实例了
1.4 MVVM模型
- M:模型:data中的数据
- V:视图:模板代码
- VM:视图模型:Vue实例
观察发现:
data
中所有属性,最后都出现在vm
上vm
上所有的属性及 Vue原型上所有属性,在 Vue 模板中都可以直接使用
1.5 数据代理
Object.defineProperty
<!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>初识Vue</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><script type="text/javascript">let number = 18let person = {name:'wy',sex:'male'}Object.defineProperty(person, 'age',{// value:13,enumerable:true, // 控制属性是否可以枚举,默认值为false// writable:true, // 控制属性是否可以被修改,默认值为false// configurable:true, // 控制属性是否可以被删除,默认值为false// 当 age 属性被读取时,get函数会被调用,且返回值是 ageget(){return number},// 当 age 属性被修改时,set函数会被调用,且会收到修改的值set(value){number = value;}})console.log(person);console.log(Object.keys(person));</script>
</body>
</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>Vue核心</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><script type="text/javascript">let obj1 = {x:1}let obj2 = {y:2}Object.defineProperty(obj2, 'x',{get(){return obj1.x},set(value){obj1.x = value;}})</script>
</body>
</html>
控制台验证
Vue中的数据代理
-
通过
vm
对象来代理data
对象中属性的操作 (读/写) -
更加方便地操作
data
中的数据 -
基本原理
通过
Object.defineProperty()
把data
对象中所有属性添加到vm
上。为每一个添加到vm
上的属性,都指定一个getter/setter
,在getter/setter
内部去操作data
中对应的属性
1.6 事件处理
事件基本使用
<!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>Vue核心</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root"><h1>{{name}}</h1><button v-on:click="showInfo1">点我提示信息1</button><button @click="showInfo2(666, $event)">点我提示信息2</button></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{name:'hh',},methods:{showInfo1(event){console.log(event.target.innerText);},showInfo2(number, event){console.log(number);console.log(event);}}})</script>
</body>
</html>
- 使用
v-on:xxx
或@xxx
绑定事件, xxx为事件名 - 事件的回调需要配置在
methods
对象中,最终会在vm
上 methods
中配置的函数,都是被Vue
所管理的函数,this
的指向是vm
或组件实例对象@click="demo"
和@click="demo($event)"
效果一致,但后者可以传递参数- 绑定事件时,
xxx
可以写一些简单的语句,不过最好在methods
中写函数封装。
事件修饰符
-
prevent
: 阻止默认事件(常用)<!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>事件修饰符/title><script type="text/javascript" src="../js/vue.js"></script> </head> <body><div id="root"><h1>{{name}}</h1><a href="https://www.baidu.com" @click="showInfo">点击</a></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{name:'hh',},methods:{showInfo(event){alert('你好')},}})</script> </body> </html>
可以发现,
a
标签的默认行为不会被执行 -
stop
: 阻止事件冒泡(常用)<script type="text/javascript">const vm = new Vue({el:'#root',data:{name:'hh',},methods:{showInfo(t){console.log(t);},}}) </script>
未添加阻止冒泡时
<div id="root"><h1>{{name}}</h1><div @click="showInfo(1)"><button @click="showInfo(2)">点击</button></div> </div>
阻止冒泡后
<div id="root"><h1>{{name}}</h1><div @click="showInfo(1)"><button @click.stop="showInfo(2)">点击</button></div> </div>
-
once
: 事件只触发一次(常用)<div id="root"><h1>{{name}}</h1><div><button @click.once="showInfo(2)">点击</button></div> </div>
多次点击后,只会执行一次
showInfo(2)
-
capture
: 使用事件的捕获模式 -
self
: 只有event.target
是当前操作的元素时才触发事件 -
passive
:事件的默认行为立即执行,无需等待事件回调执行完毕
键盘事件
Vue
常用按键别名
触发条件: keydown
和 keyup
<!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>键盘事件</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root"><input type="text" @keydown.tab="showInfo"></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{name:'hh',},methods:{showInfo(e){console.log(e.target.value);},}})</script>
</body>
</html>
补充
组合按键: <input type="text" @keydown.ctrl.y="showInfo">
修饰符组合:
<div id="root"><h1>{{name}}</h1><div @click="showInfo(1)"><a href="https://baidu.com" @click.stop.prevent="showInfo(2)">点击</button></div></div>
不会跳转
1.7 计算属性
基本使用
- 定义:要用的属性不存在,要通过已有属性计算得来
- 原理:底层借助了
Object.defineproperty
方法提供的getter
和setter
get
函数什么时候执行?- 初次读取时会执行一次
- 当计算属性所依赖的数据发生改变时会被调用
- 优势:与
methods
实现对比,内部有缓存机制(可复用),效率更高,调试方便 - 备注:
- 计算属性最终会出现在
vm
上,直接读取使用即可 - 如果计算属性被修改,那必须写
set
函数去响应修改,且set
中要引起计算时依赖的属性的数据发生改变
- 计算属性最终会出现在
<!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>计算属性</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root"><input type="text" v-model="firstName"><br/><input type="text" v-model="lastName"><br/><div><h3>{{fullName}}</h3></div></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{firstName:'张',lastName:'三',},computed:{fullName:{get(){console.log('调用get函数')return this.firstName + '-' + this.lastName},set(value){console.log('调用set函数')const arr = value.split('-') this.firstName = arr[0]this.lastName = arr[1]}}}})</script>
</body>
</html>
修改姓
修改计算属性
简写
计算属性只考虑读取,不考虑修改时,才可以进行简写
computed:{fullName(){console.log('调用get函数')return this.firstName + '-' + this.lastName}
}
1.8 监视属性
- 当被监视的属性变化时,回调函数自动调用,进行相关操作
- 监视的属性必须存在,才能进行监视
- 监视的两种写法:
new Vue
时传入watch
配置- 通过
vm.$watch
监视
基本使用
<!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>监视属性</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root"><div><h2>今天天气很{{info}}</h2><button @click="change">点击切换天气</button></div></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{ishot:true,},methods: {change(){this.ishot = !this.ishot}},computed:{info(){return this.ishot ? '炎热' : '凉爽'}},// 第一种写法watch:{ishot:{immediate:true, // 初始化时会被调用一次handler(newValue, oldValue){ // 当 ishot 被修改时会被调用console.log('ishot被修改', newValue, oldValue);}}}})// 第二种写法vm.$watch('ishot', {immediate:true,handler(newValue, oldValue){console.log('ishot被修改', newValue, oldValue);}})</script>
</body>
</html>
深度监视
Vue
中的watch
默认不监测对象内部值的改变(一层)- 配置
deep:true
可以监测对象内部值改变(多层)
备注:
Vue
自身可以监测到对象内部值的改变,但Vue
提供的watch
默认不可以- 使用
watch
时根据数据的具体结构,决定是否采用深度监视
<!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>监视属性</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root"><div><h2 @click="number.a++">{{number.a}}</h2><h2 @click="number.b++">{{number.b}}</h2></div></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{number:{a:1,b:1}},watch:{// 多级结构时写字符串形式'number.a':{handler(){console.log('a变化');}}}})</script>
</body>
</html>
此时点击 a
会输出 a变化
watch:{number:{deep:true, // 深度监视配置deep属性handler(){console.log('number变化');}}
}
简写
当 wathch
配置项只有 handler
时可以简写
vm.$watch('ishot',function(newValue, oldValue){console.log('ishot被修改', newValue, oldValue)
})
watch:{ishot(newValue, oldValue){console.log('ishot被修改', newValue, oldValue);}
}
Watch vs Computed
二者区别:
- computed 能完成的功能,watch 都能完成
- watch 能完成的功能,computed 不一定能完成,例如:watch 可以进行异步操作
两个重要的小原则:
- 被
Vue
管理的函数,最好写成普通函数,这样this
的指向才是vm
或组件实例对象 - 所有不被
Vue
管理的函数(定时器的回调函数、ajax的回调函数、promise的回调函数等),最好写成箭头函数,这样this
的指向才是vm
或 组件实例对象
1.9 绑定class和style
class
基本写法
<!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>绑定样式</title><script type="text/javascript" src="../js/vue.js"></script><style>.happy{background-color: red;}.sad{background-color: blue;}.normal{background-color: wheat;}.basic{height: 100px;width: 200px;border: solid red 1px;}</style>
</head>
<body><div id="root"><div class="basic" :class="css" @click="change"></div></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{css:'normal'},methods: {change(){styles = ['normal', 'sad', 'happy']this.css = styles[Math.floor(Math.random()*3)]}},})</script>
</body>
</html>
以上示例可以通过点击实现样式随机切换
和绑定属性值类似
:class="xxx"
xxx
可填变量,数组或对象
数组:
<body><div id="root"><div class="basic" :class="arr"></div></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{css:'normal',arr:['normal', 'sad', 'happy'],},methods: {},})</script>
</body>
对象:
<body><div id="root"><div class="basic" :class="cssObj"></div></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{cssObj:{'normal':true, // 使用 normal样式'sad':false,'happy':false,}},})</script>
</body>
style
原始写法
<div class="basic" style="font-size: 50px;">你好</div>
绑定后
<div class="basic" :style="{fontSize: size + 'px'}">你好</div>
对象写法
data:{styleObj:{fontSize: '60px',color: 'green',backgroundColor: 'yellow'}
},
前面的 key 不能乱写,一个单词正常写,两个单词用 -
连接的需要将第二个单词首字母大写,然后去掉 -
style中也可以写 数组,但不常用
1.10 条件渲染
v-if
- 写法:
v-if="表达式"
v-else-if="表达式"
v-else="表达式"
- 适用于:切换频率较低的场景
- 特点:不展示的
DOM
元素直接被移除 - 注意:
v-if
可以和v-else-if
、v-else
一起使用,但要求结构不能被打断
- 写法:
v-show
- 写法:
v-show="表达式"
- 适用于:切换频率较高的场景
- 特点:不展示的
DOM
元素未被移出,仅仅是使用样式隐藏掉
- 写法:
- 备注:使用
v-if
时,元素可能无法获取到,而使用v-show
时一定可以获取到
<!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>条件渲染</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root"><h1 v-show="0">你好</h1><h1 v-if="1 === 3">hello</h1></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{},})</script>
</body>
</html>
1.11 列表渲染
v-for
指令
- 用于展示列表数据
- 语法:
v-for="(item, index) in xxx" :key="yyy"
- 可遍历:数组、对象、字符串(使用较少)、指定次数(使用较少)
<!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>列表渲染</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root"><ul><li v-for="(val, k) in persons" :key="k">{{val.name}}--{{val.age}}</li></ul></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{persons:[{'name':'wy', 'age':20}, {'name':'wm', 'age':16},{'name':'xx', 'age':10},]}})</script>
</body>
</html>
Key作用
列表过滤
<!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>列表过滤</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root"><input type="text" v-model="keyword"><ul><li v-for="(val, k) in persons_fill" :key="k">{{val.name}}--{{val.age}}</li></ul></div><script type="text/javascript">// const vm = new Vue({// el:'#root',// data:{// keyword:'',// persons:[// {'name':'wyy', 'age':20}, // {'name':'wmx', 'age':16},// {'name':'xxw', 'age':10},// {'name':'adsf', 'age':20}, // {'name':'vcx', 'age':16},// {'name':'xwe', 'age':10},// {'name':'wyy', 'age':20}, // {'name':'wmx', 'age':16},// {'name':'xxw', 'age':10},// {'name':'adsf', 'age':20}, // {'name':'vcx', 'age':16},// {'name':'xwe', 'age':10},// ],// persons_fill:[// ]// },// watch:{// keyword:{// immediate:true,// handler(val){// this.persons_fill = this.persons.filter((p)=>{// return p.name.indexOf(val) !== -1// })// }// }// }// })const vm = new Vue({el:'#root',data:{keyword:'',persons:[{'name':'wyy', 'age':20}, {'name':'wmx', 'age':16},{'name':'xxw', 'age':10},{'name':'adsf', 'age':20}, {'name':'vcx', 'age':16},{'name':'xwe', 'age':10},{'name':'wyy', 'age':20}, {'name':'wmx', 'age':16},{'name':'xxw', 'age':10},{'name':'adsf', 'age':20}, {'name':'vcx', 'age':16},{'name':'xwe', 'age':10},],},computed:{persons_fill(){return this.persons.filter((p)=>{return p.name.indexOf(this.keyword) !== -1})}}})</script>
</body>
</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>列表排序</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root"><h1>人员列表</h1><input type="text" v-model="keyword"><button @click="sortType = 1">升序</button><button @click="sortType = 2">降序</button><button @click="sortType = 0">原序</button><ul><li v-for="(val, k) in persons_fill" :key="k">{{val.name}}--{{val.age}}</li></ul></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{keyword:'',sortType:0,persons:[{'name':'wyy', 'age':20}, {'name':'wmx', 'age':16},{'name':'xxw', 'age':10},{'name':'adsf', 'age':20}, {'name':'vcx', 'age':16},{'name':'xwe', 'age':10},{'name':'wyy', 'age':20}, {'name':'wmx', 'age':16},{'name':'xxw', 'age':10},{'name':'adsf', 'age':20}, {'name':'vcx', 'age':16},{'name':'xwe', 'age':10},],},computed:{persons_fill(){const a = this.persons.filter((p)=>{return p.name.indexOf(this.keyword) !== -1})if (this.sortType){a.sort((a, b)=>{return this.sortType === 1 ? a.age - b.age : b.age - a.age;})}return a;}}})</script>
</body>
</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>模拟数据监测</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root"></div><script type="text/javascript">let data = {name:'wy',age:23,}// 创建一个监视的实例对象,用于监视data中属性的变化const obs = new Observer(data)let vm = {}vm._data = data = obsfunction Observer(obj) {const keys = Object.keys(obj)// 汇总对象中所有属性形成一个数组keys.forEach((k)=>{Object.defineProperty(this, k, {get(){return obj[k]},set(val){obj[k] = val}})})}</script>
</body>
</html>
测试结果
Vue.set使用
向 Vue
中添加属性
注意:tartget
不能为 vm
本身或者 vm._data
<!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>Vue.set使用</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root"><h1>name: {{name}}</h1><h1>age: {{age}}</h1><h2>school</h2><h3>name: {{school.name}}</h3><h3 v-if="school.loc">loc: {{school.loc}}</h3></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{name:'wy',age:18,school:{name:'zzu',}}})</script>
</body>
</html>
方式一:
Vue.set(vm.school, 'loc', 'zz')
方式二:
vm.$set(vm.school, 'loc', 'zz')
执行结果:
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>模拟数据监测数组</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root"><h1>爱好</h1><ul><li v-for="(val, k) in hobby" :key="k">{{val}}</li></ul></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{hobby:['听音乐', '打游戏', '唱歌', '跑步']}})</script>
</body>
</html>
数组中的元素没有 getter
和 setter
方法
直接使用数组下标对其修改在页面上不会体现效果
vm._data.hobby[0] = '睡觉'
Vue
将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:
-
push()
-
pop()
-
shift()
-
unshift()
-
splice()
vm.hobby.splice(0, 1, '吃饭')
-
sort()
-
reverse()
1.12 收集表单数据
实例
<!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>收集表单数据</title><script type="text/javascript" src="../js/vue.js"></script>
</head>
<body><div id="root" @submit.prevent="submit"><form><div>账户: <input type="text" v-model.trim="userinfo.username"></div><div>密码: <input type="password" v-model="userinfo.password"></div><div>性别: 男<input type="radio" name="sex" v-model="userinfo.sex" value="male">女<input type="radio" name="sex" v-model="userinfo.sex" value="female"></div><div>年龄: <input type="number" v-model.number="userinfo.age"></div><div>爱好:<input type="checkbox" v-model="userinfo.hobby" value="eat">吃饭<input type="checkbox" v-model="userinfo.hobby" value="sleep">睡觉<input type="checkbox" v-model="userinfo.hobby" value="drink">喝酒<input type="checkbox" v-model="userinfo.hobby" value="gameing">打游戏</div><div>其他: <textarea name="" id="" cols="30" rows="10" v-model.lazy="userinfo.other"></textarea></div><button>提交</button></form></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{userinfo:{username:'',password:'',sex:'',age:'',hobby:[],other:'',}},methods: {submit(){console.log(JSON.stringify(this.userinfo));}},})</script>
</body>
</html>
1.13 过滤器
**定义:**对要显示的数据进行特定格式化后再显示(适用于一些简单逻辑的处理)
语法:
- 注册过滤器:
Vue.filter(name, callback) 或 new Vue{filters:{}}
- 使用过滤器:
{{ xxx | 过滤器名 }} 或 v-bind:属性 = "xxx | 过滤器名"
备注:
- 过滤器也可以接收额外参数、多个过滤器也可以串联
- 并没有改变原本的数据,是产生新的对应数据
实例:
<!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>过滤器</title><script type="text/javascript" src="../js/vue.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.4/dayjs.min.js"></script>
</head>
<body><div id="root"><h1>显示当前日期和时间</h1><h2>{{ time | getTime }}</h2><h1>显示时间</h1><h2>{{ time | getTime('HH:mm:ss') }}</h2><h1>属性绑定</h1><h2 :x="time | getTime">你好</h2><h1>截取前4位</h1><h2>{{ time | getTime | slice(0, 4) }}</h2></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{time:1659925371764},methods:{},filters:{getTime(value, str='YYYY年MM月DD日 HH:mm:ss'){return dayjs(value).format(str)},slice(str, st=0, ed=0) {return str.slice(st, ed)}}})</script>
</body>
</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>过滤器</title><script type="text/javascript" src="../js/vue.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.4/dayjs.min.js"></script>
</head>
<body><div id="root"><h1>显示当前日期和时间</h1><h2>{{ time | getTime | slice(0, 4) }}</h2><h1>显示时间</h1><h2>{{ time | getTime('HH:mm:ss') }}</h2><h1>属性绑定</h1><h2 :x="time | getTime">你好</h2><h1>截取前4位</h1><h2>{{ time | getTime | slice(0, 4) }}</h2></div><script type="text/javascript">Vue.filter('getTime', function(value, str='YYYY年MM月DD日 HH:mm:ss'){return dayjs(value).format(str)})Vue.filter('slice', function(str, st=0, ed=0){return str.slice(st, ed)})const vm = new Vue({el:'#root',data:{time:1659925371764},methods:{},})</script>
</body>
</html>
1.14 内置指令
v-text
- 作用:向其所在节点中渲染文本内容
- 与插值语法的区别:
v-text
会替换掉节点的内容,{{xx}}
不会
v-html
- 作用:向指定节点中渲染包含html结构的内容
- 与插值语法的区别:
v-html
会替换掉节点中所有内容,{{xxx}}
不会v-html
可以识别为html结构
- 严重注意:
v-html
有安全性问题- 在网站上动态渲染任意 html 是非常危险的,容易导致 XSS 攻击
- 一定在可信的内容上使用
v-html
,永远不要用在用户提交的内容上
v-cloak
- 本质是一个特殊的属性,Vue实例创建完毕并接管容器后,会删掉
v-cloak
属性 - 使用 css 配合
v-cloak
可以解决网速慢时页面展示出{{xxx}}
的问题
实例
<!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>v-cloak</title><script type="text/javascript" src="../js/vue.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.4/dayjs.min.js"></script><style>[v-cloak]{display: none;}</style>
</head>
<body><div id="root"><h1 v-cloak>{{name}}</h1></div><script type="text/javascript">Vue.filter('getTime', function(value, str='YYYY年MM月DD日 HH:mm:ss'){return dayjs(value).format(str)})Vue.filter('slice', function(str, st=0, ed=0){return str.slice(st, ed)})const vm = new Vue({el:'#root',data:{name:'张三'}})</script>
</body>
</html>
v-once
v-once
所在节点在初次动态渲染后,就视为静态内容了- 以后数据的改变不会引起
v-once
所在结构的更新,可以用于优化性能
v-pre
- 跳过其所在节点的编译过程
- 可利用它跳过节点:没有使用指令语法、没有使用插值语法的节点,加快编译
<!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>v-cloak</title><script type="text/javascript" src="../js/vue.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.4/dayjs.min.js"></script></head>
<body><div id="root"><h1 v-pre @click="name += '1'">{{name}}</h1></div><script type="text/javascript">Vue.filter('getTime', function(value, str='YYYY年MM月DD日 HH:mm:ss'){return dayjs(value).format(str)})Vue.filter('slice', function(str, st=0, ed=0){return str.slice(st, ed)})const vm = new Vue({el:'#root',data:{name:'张三'}})</script>
</body>
</html>
1.15 自定义指令
注意自定义命令中的 this
是 Windows
<!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>自定义指令</title><script type="text/javascript" src="../js/vue.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.4/dayjs.min.js"></script></head>
<body><div id="root"><h1>{{n}}</h1><button @click="n++">点击</button><input type="nubmer" v-fbind="n"></div><script type="text/javascript">Vue.filter('getTime', function(value, str='YYYY年MM月DD日 HH:mm:ss'){return dayjs(value).format(str)})Vue.filter('slice', function(str, st=0, ed=0){return str.slice(st, ed)})const vm = new Vue({el:'#root',data:{n:1,},directives:{// fbind(element, binding){// console.log(element, binding);// element.value = binding.value;// element.focus() // 在第一次绑定时,还没有将所在元素插入页面中,因此不会生效// }fbind:{bind(elem, binding){console.log('bind');elem.value = binding.value},inserted(elem, binding){console.log('inserted');elem.focus()},update(elem, binding){console.log('update');elem.value = binding.value}}}})</script>
</body>
</html>
1.16 生命周期
- 又名:生命周期回调函数、生命周期函数,生命周期钩子
- 是什么:Vue 在关键时期帮我们调用的一些特殊函数
- 生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的
- 生命周期函数中的
this
指向的是 vm 或组件实例对象
<!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>生命周期</title><script type="text/javascript" src="../js/vue.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.4/dayjs.min.js"></script></head>
<body><div id="root"><h1 :style="{opacity}">Hello, World!</h1></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{opacity:1},mounted() {setInterval(()=>{this.opacity -= 0.01if (this.opacity <= 0) this.opacity = 1}, 16)},})</script>
</body>
</html>
常用的生命周期钩子:
- mounted: 发送 ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】
- beforeDestroy: 清除定时器、解绑自定义事件取消订阅消息等【收尾工作】
关于销毁 Vue 实例
- 销毁后借助 Vue 开发工具看不到任何信息
- 销毁后自定义事件会失败,但原生DOM事件依然有效
- 一般不会在 beforedestroy操作数据,因为即便操作数据,也不会触发更新流程了
<!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>生命周期</title><script type="text/javascript" src="../js/vue.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.4/dayjs.min.js"></script></head>
<body><div id="root"><h1 :style="{opacity}">Hello, World!</h1><button @click="hack">点击销毁vm实例</button></div><script type="text/javascript">const vm = new Vue({el:'#root',data:{opacity:1},methods: {hack(){this.$destroy()}},beforeCreate() {console.log('beforeCreate');},created() {console.log('created');},beforeMount() {console.log('beforeMount');},mounted() {console.log('mounted');setInterval(()=>{this.opacity -= 0.01if (this.opacity <= 0) this.opacity = 1}, 16)},beforeUpdate() {console.log('beforeUpdate')},updated() {console.log('updated'); },beforeDestroy() {console.log('beforeDestroy');},destroyed() {console.log('destroyed');},})</script>
</body>
</html>
参考资料
尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通
https://www.bilibili.com/video/BV1Zy4y1K7SH?p=15&share_source=copy_web&vd_source=d3c9ceb0642f45fbe95f795c0d074040Vue 官方文档
https://cn.vuejs.org/v2/guide/
Vue api 文档
https://cn.vuejs.org/v2/api/