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 = 20
this.persons[0].sex = '男'
}
},
但是一旦我们换一个方法,我们使用一个新的对象来替换原来的对象的方法,就不能被 vue 监测到数据的变化,在页面中显示的还是原来被替换前的数据,但是数据确实被改变了,只是vue 无法监测而无法改变。
methods: {
updataZhang() {
this.persons[0] = { id: '001', name: '李一百', age: 20, sex: '男' }
}
},