Vue的监测
- vue会监测data中所有层次的数据。
- vue检测对象中的数据的原理:通过setter实现监测,且要在new Vue时就传入要检测的数据。
- 对象中后追加的属性,vue默认不作响应式处理
- 如果要给后添加的属性做响应式,要使用一下API来添加属性:Vue.set(target, propertyName/index, value)或者vm.$set(target, propertyName/index, value)
- vue检测数组中的数据的原理:通过包裹数组更新元素的方法实现,本质是,调用原生的对应的方法对数组进行更新,然后重新解析模板,进而更新页面
- 在vue修改数组中的某个元素时一定要使用如下方法:
- 使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
- Vue.set()或者vm.$set()
- Vue.set()或者vm.$set()不能给 vm 或者 vm的根数据对象 添加属性
监测测试案例:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><link rel="icon" href="favicon.ico"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Vite App</title><script type="text/javascript" src="../vue.js"></script></head><body><div id="root"><h3>你好,{{name}} </h3><br/><h3>学生姓名是:{{student.name}}</h3><h3>学生年龄是:{{student.age}}</h3><h3>学生性别是:{{student.sex}}</h3><ul><li v-for="(person,index) in persons" :key="person.id">姓名:{{person.name}} --年龄:{{person.age}}</li></ul><button @click="student.age++">年龄加一</button><button @click="addSex">添加性别</button><button @click="addFriend">添加人员</button><button @click="updateFirstFriendName">更新第一人名字</button></div></body><script type="text/javascript">let vm = new Vue({el:'#root',data:{name:'李二狗',student:{age:19,name:"曼波"},persons:[{id:'001',name:'张三',age:18},{id:'002',name:'李四',age:19},{id:'003',name:'王五',age:20}]},methods:{addSex(){Vue.set(this.student,"sex","男")//this.$set(this.student,"sex","男")},addFriend(){this.persons.unshift({id:"004",name:"jack",age:19})},updateFirstFriendName(){this.persons[0].name = "哈基米"}}})</script>
</html>
收集表单数据
- 若是文本框这种输入类型,v-model收集的是value属性的值,用户输入的内容就是value
- 若是单选框,v-model收集的是选项的value,要给选项配好value属性
- 若是多选框,没有配置value属性,那么收集的就是checked属性(勾选就是true,不勾选就是false)。配置了value值后,绑定的data中的数据要是一个数组,各个多选的值会成为数组中的元素。
- v-model的三个修饰符:
- lazy:失去了焦点再收集数据,默认是边输入边收集
- number:输入的字符串转化为数字
- trim:输入首尾空格过滤
收集表单数据案例:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><link rel="icon" href="favicon.ico"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Vite App</title><script type="text/javascript" src="../vue.js"></script></head><body><div id="root"><form><label for="demo">账号:</label><input type="text" id="demo" v-model="account"><br><br><label for="demo2">密码:</label><input type="password" id="demo2" v-model="password"><br><br>性别:<br><label for="man">男</label><input type="radio" id="man" name="sex" value="man" v-model="sex"><label for="woman">女</label><input type="radio" id="woman" name="sex" value="woman" v-model="sex"><br><br>爱好:<br><label for="sing">唱</label><input type="checkbox" id="sing" name="hobby" v-model="hobby" value="sing"><label for="dance">跳</label><input type="checkbox" id="dance" name="hobby" v-model="hobby" value="dance"><label for="rap">rap</label><input type="checkbox" id="rap" name="hobby" v-model="hobby" value="rap"><label for="basketball">篮球</label><input type="checkbox" id="basketball" name="hobby" v-model="hobby" value="basketball"><br><br>所属校区:<select name="schoolArea" id="schoolArea" v-model="schoolArea"><option value=""></option><option value="jiangxi"> 江西 </option><option value="henan"> 河南 </option><option value="zhejiang"> 浙江 </option></select><br><br/>其他信息:<textarea v-model="other"></textarea><br><br><input type="checkbox" v-model="agree"><a href="<http://www.atguigu.com>">《用户协议》</a><br><br><button>提交</button></form></div></body><script type="text/javascript">let vm = new Vue({el:'#root',data:{account:"",password:"",sex:"",hobby:[],schoolArea:"",other:"",agree:""}})</script>
</html>
过滤器
过滤器用于对要使用的数据进行特定操作后再使用(适用于一些简单的逻辑),产生的是一个经过处理的新数据。
注册过滤器
局部过滤器
使用Vue实例的filters属性进行注册过滤器,例:
new Vue({el:"#root",data:{hello:"哈哈哈",time:1621561377603 //时间戳},computed:{fmtTime(){return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')}},//局部过滤器filters:{filterTest(value){return dayjs(value).format('YYYY-MM-DD HH:mm:ss')},filterTest2(value,str="YYYY-MM-DD HH:mm:ss"){return dayjs(value).format(str)},mySlice(value){return value.slice(0,4)}}})
在filters属性中,其中的方法的方法名就是过滤器的名称,return返回的是过滤后的结果,value和其他参数的说明在以下过滤器的使用中阐述。
全局过滤器
使用Vue.filter(name,callbackFunction)注册全局过滤器,要在Vue实例的初始化之前就注册,例:
//全局过滤器Vue.filter("mySlice2",function(value){return value.slice(0,2)})
过滤器的使用
在表达式中,比如{{}}中的表达式或者一些属性(v-bind等)的属性值表达式中,使用管道符来表示使用过滤器,最终的结果就是过滤器产生的结果,例:
<h3>(过滤器)现在是:{{time | filterTest}}</h3>
此时time便会变成以上过滤器中的方法(见局部过滤器中的案例)的那个value参数,即管道符左边的表达式的结果会变成管道符右边的过滤器的value参数。
如果要加入别的参数,在管道符右边的过滤器中加上括号,在括号中加入其他参数即可,但是此时的管道符右边的参数在filters属性的方法中是从第二个参数算起的,因为第一个参数永远是管道符左边表达式的结果产生的value值(即管道符右边的第一个参数是filters中的方法的第二个参数,第二个参数是filters中的第三个参数,以此类推)。例:
<h3>(过滤器)现在是:{{time | filterTest2("YYYY-MM-DD")}}</h3>
同时,过滤器还可以嵌套使用,计算顺序是从左到右,即第二个过滤器产生的结果就是第三个过滤器的value参数值,例:
<h3>(过滤器)现在是:{{time | filterTest2("YYYY-MM-DD") | mySlice}}</h3>
过滤器的整体案例如下
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><link rel="icon" href="favicon.ico"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="<https://cdn.bootcdn.net/ajax/libs/dayjs/1.11.12/dayjs.min.js>"></script><script type="text/javascript" src="../vue.js"></script>
</head>
<body><div id="root"><h2>显示格式化之后的时间</h2><h3>现在是:{{fmtTime}}</h3><h3>(过滤器)现在是:{{time | filterTest}}</h3><h3>(过滤器)现在是:{{time | filterTest2("YYYY-MM-DD")}}</h3><h3>(过滤器)现在是:{{time | filterTest2("YYYY-MM-DD") | mySlice}}</h3><h3>{{hello | mySlice2}}</h3></div><div id="root2"><h2>{{msg | mySlice2}}</h2></div>
</body>
<script>//全局过滤器Vue.filter("mySlice2",function(value){return value.slice(0,2)})new Vue({el:"#root",data:{hello:"哈哈哈",time:1621561377603 //时间戳},computed:{fmtTime(){return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')}},//局部过滤器filters:{filterTest(value){return dayjs(value).format('YYYY-MM-DD HH:mm:ss')},filterTest2(value,str="YYYY-MM-DD HH:mm:ss"){return dayjs(value).format(str)},mySlice(value){return value.slice(0,4)}}})new Vue({el:"#root2",data:{msg:"你好呀"}})
</script>
</html>
其他内置指令
内置指令复习
v-bind:单向绑定解析表达式
v-model:双向数据绑定
v-for:遍历数组、对象、字符串
v-on:绑定事件监听,可以简写为@
v-if:条件渲染(动态控制节点是否存在)
v-else:条件渲染(动态控制节点是否存在)
v-show:条件渲染(动态控制节点是否展示)
v-text
作用是解析表达式中的内容,渲染文本内容。
与插值语法的区别:v-text解析后会替换掉整个节点的文本内容,而插值表达式可以动态渲染部分文本内容
v-html
作用是向指定节点中渲染包含html结构的内容。
也是会替换整个节点的所有内容,与v-text的区别是v-html可以识别并解析html结构。
在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
一定要在可信的内容上使用v-html,不要使用在用户提交的内容上
v-cloak
没有属性值,Vue实例创建完成后并接管容器后,会删掉v-cloak属性。
使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题
v-once
没有属性值,v-once所在节点在初次动态渲染后,就视为静态内容了。
以后数据的改变不会引起v-once所在的结构的更新。
v-pre
没有属性值,跳过其所在的节点的编译过程。
可以利用其跳过没有使用指令语法、没有使用插值语法的节点,会加快编译。
自定义指令
自定义指令在directives属性中进行定义,定义方式有两种
函数式
在directives属性中,新建方法,方法名为自定义自定义指令的指令名。方法有两个参数:
- element:代表该自定义指令绑定的那个节点的DOM(为真实DOM)
- binging:其中有一些指令相关的信息,比如指令的属性值对应的表达式,指令属性值对应的值(也就是表达式的结果),指令对应的值用binging.value表示
然后在方法内进行定义指令的逻辑,例:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><link rel="icon" href="favicon.ico"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Vite App</title><script type="text/javascript" src="../vue.js"></script></head><body><div id="root"><h2>当前的n值是:<span v-text="n"></span></h2><h2>放大十倍后的n值是:<span v-big="n"></span></h2><button @click="n++">点我n+1</button></div></body><script type="text/javascript">let vm = new Vue({el:'#root',data:{name:'李二狗',n:12},directives:{big(element,binding){element.innerText = binding.value * 10}}})</script>
</html>
对象式
在directives属性中,使用对象的形式表示自定义指令的创建,该对象的属性名为自定义指令的指令名。对象中有三个常用方法:
- bind方法:当指令与元素成功绑定时调用
- inserted方法:指令所在元素被插入页面时
- update方法:指令所在的模板被重新解析时
函数式的逻辑其实就是bind方法和update方法用同一个方法体,结合在一起,不过没有inserted,也不能将bind和update方法的逻辑分离。
案例:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><link rel="icon" href="favicon.ico"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Vite App</title><script type="text/javascript" src="../vue.js"></script></head><body><div id="root"><h2>当前的n值是:<span v-text="n"></span></h2><h2>放大十倍后的n值是:<span v-big="n"></span></h2><button @click="n++">点我n+1</button><hr><hr><input type="text" v-fbind:value="n"></div></body><script type="text/javascript">let vm = new Vue({el:'#root',data:{name:'李二狗',n:12},directives:{big(element,binding){element.innerText = binding.value * 10},fbind:{//当指令与元素成功绑定时调用此函数bind(element,binding){element.value = binding.value},//指令所在元素被插入页面时调用inserted(element,binding){element.focus()},//指令所在的模板重新被解析时调用update(element,binding){element.value = binding.valueelement.focus()}}}})</script>
</html>
注:
- 如果自定义指令的指令名是xxxx-xxxx这种格式的,那么在directives属性中的写法就要写为原始的形式,即属性名为字符串形式,方法也不能使用简写形式,要使用原来的”key”:function(){ }形式
- 如果定义全局的自定义指令,要使用Vue.directives(”指令名”, 函数式/对象式 写法)