shsh一、绑定 class 样式
(一)字符串写法
1.流程介绍
适用于样式的类名不确定 需要动态指定
通过 指令绑定的形式,在模板中的类标签绑定 Vue 实例中的数据 mood
<div class="basic" :class="mood" @click="changeMood">test</div>
在实例对象的 data 加入 mood 属性并且 用对应的类名赋值
data: {name: '一个人',mood: 'normal'},
根据以上原理 我们能设计出 一个点击切换样式的效果
点击切换成 happy 类名 中的样式
2.代码实现
<body><div id="root"><div class="basic" :class="mood" @click="changeMood">test</div><script>new Vue({el: '#root',data: {name: '一个人',mood: 'normal'},methods: {changeMood() {this.mood = 'happy'}},})</script></div>
</body>
随机显示背景颜色函数设计,把三个类名存到数组中,然后随机取下标,进行读取就行
methods: {changeMood() {const arr = ['happy', 'sad', 'normal']const index = Math.floor(Math.random() * 3)this.mood = arr[index]}},
(二)数组写法
1.流程介绍
适用于绑定的样式个数不确定,名字也不确定
想要随时添加样式删除样式 就在模板中 插值一个数组类型的数据
<div class="basic" :class="arr" @click="changeMood">test</div>
然后在 data 中添加一个数组类型的数据,在数组里面放入我们要展示的类名 ,我们还能通过操作数组进行,增加和删除样式
data: {name: '一个人',mood: 'normal',arr:['normal','happy','bianhua'],},
删除
vm.arr.shift()
增加
vm.arr.push('增加的类名')
2.代码实现
<body><div id="root"><div class="basic" :class="arr" @click="changeMood">test</div></div><script>new Vue({el: '#root',data: {arr:['normal','happy','bianhua'],},})</script></div>
</body>
(三)对象写法
1.流程介绍
适用于绑定的样式确定 名字也确定 要动态决定用不用
先绑定对象
<div class="basic" :class="Obj" @click="changeMood">test</div>
在实例对象 vm 中的 data 对象中写一个对象类型数据 里面放着样式类名 通过 true 和 false 来判断使用不使用这个样式
data: {name: '一个人',mood: 'normal',arr:['normal','happy','bianhua'],Obj:{happy:true,bianhua:true}},method
2.代码实现
<body><div id="root"><div class="basic" :class="Obj" @click="changeMood">test</div></div><script>new Vue({el: '#root',data: {Obj:{happy:true,bianhua:true}},})</script></div>
</body>
二、绑定 style 样式(了解)
除了可以用 class 绑定样式 我们还可以通过内联 style 来绑定样式
(一)对象写法
先绑定对象
<div class="basic" :style="Obj" @click="changeMood">test</div>
在实例对象 vm 中的 data 对象中写一个样式对象,里面的属性就是我们要设置的样式,属性名不能随便写,得遵循 css 中的属性名
Obj: {fontSize: '40px'}
(二)数组写法
不常用,如果要写很多的样式 我们能分开写
<div class="basic" :style="Obj" @click="changeMood">test</div>
styleArr:[{ fontSize: '40px' },{backgroundColor: 'blue'}]
三、条件渲染
(一)v-show 渲染
变化频率高的时候使用v-show
隐藏标签的内容,节点还在但是被隐藏了
v-show=‘false’ 内容隐藏 true 就是显示
<h2 v-show="false">欢迎来到{{name}}</h2>
引号里面可以写表达式,还有 vm 中的数据 ,比如 v-show='a' 在 vm 实例的数据中添加 a 的具体值 实现动态的显示和隐藏
还能写 v-show=‘a=1’ 判断布尔值 具体是什么 为真则显示 假则隐藏
(二)v-if 渲染
变化频率低的时候使用v-if 因为很暴力不展示的元素直接删除
1.v-if
判断里面是否为真为真就显示 为假就删除
<h2 v-if="false">欢迎来到{{name}}</h2>
2.v-else-if
和 if 和 elseif 使用方法类似 先判断 if 如果不符合 再依次往下判断 但是一旦为真 就不再判断下面的了,如果同时三个 v-if 则每行语句都需要重新判断。
<div v-if="n===1">n=1</div><div v-else-if="n===2">n=2</div><div v-else-if="n===3">n=3</div>
3.v-else
和 else 用法差不多 但是后面不要接数值了 ,如果 v-if 和v-else-if 中的语句都为假 就显示 v-else 中的语句
<div v-if="n===1">n=1</div><div v-else-if="n===2">n=2</div><div v-else-if="n===3">n=3</div><div v-else>n是个厉害</div>
4.注意事项
v-if 不允许被打断
如果在v-else-if 中间添加了其他的标签,就不会执行后面的语句。下面只能输出 n=1 和 n=2 其它找不到了
<div v-if="n===1">n=1</div><div v-else-if="n===2">n=2</div><div>@</div><div v-else-if="n===3">n=3</div><div v-else>n是个厉害</div>
模板标签 tempalate
如果想让下面几个 h2 标签都在 a=1 时显示出来
我们可能会想到每个标签都加一个 v-if 判断条件的写法 但是太复杂
<h2 v-if="true">你好</h2><h2 v-if="true">您好</h2><h2 v-if="true">我们好</h2>
我们可以用一个模板 template 来包裹这些都要显示的标签,然后给这个模板一个 v-if=’n===1‘,就可以控制所有的标签的显示了,而且使用模板不会影响标签结构,当展示出来的时候模板会自动脱落,记住不能和 v-show 使用
<template v-if="n === 1 "><h2>你好</h2><h2>您好</h2><h2>我们好</h2></template>
四、列表渲染
(一)v-for 遍历
1.遍历数组
数组信息:
persons:[{id: '001',name: '张三',age: 18},{id: '002',name: '李四',age: 19},{id: '003',name: '王五',age: 20},],
遍历生成相同 的 结构标签 前面一个变量 代表后面的数组每次遍历的当前元素
in 可以换成 of
<li v-for="p in persons">{{p.name}}-{{p.age}}</li>
里面最好写上每个生成的 li 标签的 key 值就是每个生成出的标签独特的标识 ,每个生成的 li 的 key 值应该不同 切忌写成 :key='1' 这样每个生成的 li 标签的 key 值相同就会报错,就和身份证不能一样类比。
<li v-for="p in persons" :key='p.id'>{{p.name}}-{{p.age}}</li>
其 v-for=‘p in persons’ in 前面可以有两个变量,完整写法是 v-for=‘(p,index) in persons’
括号里面第一个变量代表后面的数组每次遍历的当前元素,第二代表当前元素的下标
所以我们 的 key 值还有第二种写法
<li v-for="(p,index) in persons" :key='index'>{{p.name}}-{{p.age}}</li>
2.遍历对象
对象信息:
car:{name:'小汽车',price:'100万',color:'白色'}
遍历对象
和遍历数组类似,在遍历对象时前面也会收到两个数据 第一个是 value 就是当前属性的属性值
key 是当前属性的属性名
<li v-for="(value,k) in car" :key="k">{{k}}-{{value}}</li>
3.遍历字符串 少见
str:'hello'
和前面类似 v-for 里面也会收到两个数据 一个是 当前字符 另一个是当前字符的下标
<li v-for="(char,index) in str" :key="index">{{char}}-{{index}}</li>
4.遍历指定次数 特别少见
下面是只当遍历 5 次
number 是从1开始的数字 1 2 3 4 5 index 是从 0 开始的下标 0 1 2 3 4
<li v-for="(number,index) in 5" :key="index">{{number}}-{{index}}</li>
(二)v-for 中 key 的原理
1.简单介绍
key 如果不写默认是 下标就是 index
key 的作用就是给节点进行标识 类似于人类的身份证号,在页面中查看真实 dom 结构发现 li 没有 key 属性 因为key 被 Vue 内部使用,当 Vue 把 li 转化成真实 dom 节点时就把 key 这个特殊属性征用了,给 Vue 自己用 不给别人显示,如果换成别的属性名就显示了
<li v-for="(p,index) in persons" :key="index">{{p.name}}-{{p.age}}</li>
2.常见错误
但是如果使用 index 作为 key 的 值使用 一定情况下会发生错误,比如我们想三个人前面加一个王五,但是我们先在每个人后面添加一个文本框,然后输入三个人的信息,然后再添加这个王五,我们发现信息篡位了,具体流程如下:通过虚拟 dom 节点的(diff)对比算法 进行更新
效率较低,因为复用的比较少
我们可以通过使用 id 来作为 key 的值来使用来解决这个问题,数据不会错位也提高了代码的效率
3.总结
1.可能产生的问题:
逆序添加数据,删除数据 破坏顺序的行为 会产生没有必要的真实dom 的更新,界面效果没问题,但是效率低。
如果结构中包含输入类的dom 会产生错误的 dom 更新 界面有问题
2.如何选择 key :
使用每一条数据的唯一标识符为 key ,比如 id 手机号 身份证号唯一值
如果不存在逆序增加 删除 破坏顺序的操作,仅用于渲染列表用于展示,使用 index 作为 key 是没问题的
(三)列表信息过滤
1.使用 watch 监听实现
过滤器返回值是过滤数组的条件
空字符串包含在任何字符串之中,返回值是 0 不是 -1 所以能返回过滤数组
<body><div id="root"><h2>人员列表</h2><input type="" placeholder="请输入名字" v-model="keyword"><ul><li v-for="(p,index) in filPersons" :key="index">{{p.name}}-{{p.age}}-{{p.sex}}</li></ul></div><script>new Vue({el: '#root',data: {keyword: '',persons: [{ id: '001', name: '李三', age: 18, sex: '女' },{ id: '002', name: '李四', age: 19, sex: '男' },{ id: '003', name: '王四', age: 20, sex: '男' },],filPersons:[]},watch: {keyword:{immediate:true,handler(val) {this.filPersons = this.persons.filter((p) => {return p.name.indexOf(val) !== -1})}}}})</script>
</body>
2.使用 计算属性 监听实现
计算属性中 return 中才是返回的新的数组,不用在 data 中新创建一个空的数组来存最后的数据,不用给数组重新赋值
<body><div id="root"><h2>人员列表</h2><input type="" placeholder="请输入名字" v-model="keyword"><ul><li v-for="(p,index) in filPersons" :key="index">{{p.name}}-{{p.age}}-{{p.sex}}</li></ul></div><script>new Vue({el: '#root',data: {keyword: '',persons: [{ id: '001', name: '李三', age: 18, sex: '女' },{ id: '002', name: '李四', age: 19, sex: '男' },{ id: '003', name: '王四', age: 20, sex: '男' },],},computed: {filPersons() {return this.persons.filter((p) => {return p.name.indexOf(this.keyword) !== -1})}}})</script>
</body>
(四)列表排序
在过滤后的数组中进行操作,只要里面任何属性发生变化,就会重新调用
<body><div id="root"><h2>人员列表</h2><input type="" placeholder="请输入名字" v-model="keyword"><button @click="sortType = 2">年龄升序</button><button @click="sortType = 1">年龄降序</button><button @click="sortType = 0">原顺序</button><ul><li v-for="(p,index) in filPersons" :key="index">{{p.name}}-{{p.age}}-{{p.sex}}</li></ul></div><script>new Vue({el: '#root',data: {keyword: '',persons: [{ id: '001', name: '李三', age: 18, sex: '女' },{ id: '002', name: '李四', age: 50, sex: '男' },{ id: '003', name: '王四', age: 30, sex: '男' },],sortType: 0,},computed: {filPersons() {const arr = this.persons.filter((p) => {return p.name.indexOf(this.keyword) !== -1})if (this.sortType) {arr.sort((p1, p2) => {return this.sortType === 1 ? p2.age - p1.age : p1.age - p2.age})}return arr}}})</script>
</body>
五、Vue 检测数据原理
很重要,我们把 data 中的数据更改 vue 会有一个内置的watch监测,然后在页面中更改新的数据,这节我们得明白不是所有的,更改的情况我们 vue 都能监测并认可更改的,有的时候可能数据变了,但是vue 监测不到,数据不会更改
如下 我们想对数组对象中的第一对象中的属性进行修改,使用下面我们构造的方法,挨个属性进行修改,能成功实现更改第一个对象的属性,并成功被 vue 监测到 新的数据在模板中能成功显现出来
methods: {updataZhang() {this.persons[0].name = '李一百'this.persons[0].age = 20this.persons[0].sex = '男'}},
但是一旦我们换一个方法,我们使用一个新的对象来替换原来的对象的方法,就不能被 vue 监测到数据的变化,在页面中显示的还是原来被替换前的数据,但是数据确实被改变了,只是vue 无法监测而无法改变。
methods: {updataZhang() {this.persons[0] = { id: '001', name: '李一百', age: 20, sex: '男' }}},