10.绑定样式
提前定义好需要用的样式
<style>
.basic{
width: 400px;
height: 100px;
border: 1px solid black;
}
.happy{
border: 4px solid red;
background-color: rgba(255, 255, 0, 0.644);
background: linear-gradient(30deg,yellow,pink,orange,yellow);
}
.normal{
background-color: skyblue;
}
.atguigu1{
background-color: yellowgreen;
}
.atguigu2{
font-size: 30px;
text-shadow:2px 2px 10px red;
}
.atguigu3{
border-radius: 20px;
}
</style>
10.1class样式
字符串写法
适用于:样式的类名不确定,需要动态指定
<div class="basic" :class="mood" @click="changeMood">{{name}}</div>
new Vue({
data:{
name:'皓月',
mood:'normal'
}
method:{
//随机切换样式
changeMood(){
const arr = ['happy','sad','normal']
//对随机数向下取整
const index = Math.floor(Math.random()*3)
this.mood = arr[index]
}
}
})
数组写法
适用于:要绑定的样式个数不确定、名字也不确定,
//第一种写法,比较灵活,可以删掉数组中任意一个也可以修改数组中任意一个
<div class="basic" :class="classArr">{{name}}</div>
const vm = new Vue({
data:{
name:'皓月',
classArr:['atguigu1','atguigu2','atguigu3']
}
})
//删除atguigu1样式 结果classArr:['atguigu2','atguigu3']
vm.classArr.shift('atguigu1')
//添加happy样式 结果classArr:['atguigu2','atguigu3','happy']
vm.classArr.push('happy')
//第二种写法(不推荐)
<div class="basic" :class="['atguigu1','atguigu2','atguigu3']">{{name}}</div>//数据写死了
data:{
name:'皓月',
}
//改进
<div class="basic" :class="[a,b,c]">{{name}}</div>
data:{
name:'皓月',
a:'atguigu1',
b:'atguigu2',
c:'atguigu3'
}
对象写法
适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用
//第一种写法
<div class="basic" :class="classObj">{{name}}
const vm = new Vue({
data:{
name:'皓月',
classObj:{
atguigu1:false,
atguigu2:true,
}
}
})
//第二种写法(不推荐)
<div class="basic" :class="atguigu1:a,atguigu2:b,">{{name}}
data:{
name:'皓月',
classObj:{
a:false,
b:true,
}
}
10.2style样式
对象写法
//第一种写法(不推荐)
<div class="basic" :style="{fontSize:fsize+'px'}">{{name}}</div>
data:{
name:'皓月'
fsize:40
}
//第二种写法(推荐)
<div class="basic" :style="styleObj">{{name}}</div>
data:{
name:'皓月',
styleObj:{
fontSize:'40px',
color:'red'
}
}
数组写法
//第一种写法
<div class="basic" :style="styleObj,styleObj2">{{name}}</div>
data:{
name:'皓月',
styleObj:{
fontSize: '40px',
color:'red',
},
styleObj2:{
backgroundColor:'orange'
}
}
//第二种写法
<div class="basic" :style="styleArr">{{name}}</div>
data:{
name:'皓月',
styleArr:[
{
fontSize: '40px',
color:'blue',
},
{
backgroundColor:'gray'
}
]
}
11.条件渲染
11.1 v-show
写法: v-show="表达式"
特点: 不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
适用于: 切换频率较高的场景。
实例:
<div>
//可以通过改变vm.a的值(true/false)动态控制h2标签的显示与隐藏
<h2 v-show='a'>欢迎{{name}}</h2>
//表达式写法,值为真-显示
<h2 v-show="1 === 1">欢迎来到{{name}}</h2>
</div>
const vm = new Vue({
el:'#root',
data:{
name:'皓月',
a:false
}
})
11.2 v-if
写法: v-if="表达式"
特点: 不展示的DOM元素直接被移除。
适用于: 切换频率较低的场景。
实例:
<h2 v-if="false">欢迎来到{{name}}</h2>
<h2 v-if="1 === 1">欢迎来到{{name}}</h2>
11.3 v-else-if
写法: **v-else-if="表达式"**
v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。
示例:
<div v-if="n === 1">Angular</div>
<div v-else-if="n === 2">React</div>
//往下找不到if,结构被打断,后面的不会渲染
<div>@</div>
<div v-else-if="n === 3">Vue</div>
<div v-else>哈哈</div>
11.4 v-if和v-show的区别
共同点: 都是动态显示DOM元素
区别:
| v-if | v-show |
|---|---|
| 动态的向DOM树内添加或者删除DOM元素 | 通过设置DOM元素的display样式属性来控制显示与隐藏 |
| 惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译 | 任何条件下(首次条件是否为真)都被编译,然后被缓存,而且 DOM 元素保留 |
12.列表渲染
12.1 v-for
- 用于展示列表数据
- 语法:v-for="(item, index) in xxx" :key="yyy"
- 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少) 实例:
遍历数组(常用)
<h2>人员列表(遍历数组)</h2>
<ul>
//有两个形参,p是遍历的每一项,index是索引值
<li v-for="(p,index) in persons" :key="index">
{{p.name}}-{{p.age}}
</li>
</ul>
data:{
persons:[
{id:'001',name:'张三',age:18},
{id:'002',name:'李四',age:19},
{id:'003',name:'王五',age:20}
]
}
遍历对象
<ul>
//第一个形参是value,第二个形参是key
<li v-for="(value,k) in car" :key="k">
{{k}}-{{value}}
</li>
</ul>
data:{
car:{
name:'奥迪A8',
price:'70万',
color:'黑色'
}
}
遍历字符串
<ul>
//第一个形参是遍历的每个字符,第二个形参是索引值
<li v-for="(char,index) in str" :key="index">
{{char}}-{{index}}
</li>
</ul>
data:{
str:'hello'
}
遍历指定次数
<ul>
//number为(1-5),index为(0-4)
<li v-for="(number,index) of 5" :key="index">
{{index}}-{{number}}
</li>
</ul>
12.2 key的原理
key的作用:key是节点的唯一标识,能尽可能的复用DOM元素
面试题:react、vue中的key有什么作用?(key的内部原理)
1. 虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】
随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
2.对比规则:
(1).旧虚拟DOM中找到了与新虚拟DOM相同的key:
①.若虚拟DOM中内容没变, 直接使用之前的真实DOM!
②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。
(2).旧虚拟DOM中未找到与新虚拟DOM相同的key
创建新的真实DOM,随后渲染到到页面。
3.用index作为key可能会引发的问题:
- 若对数据进行逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低。
- 如果结构中还包含输入类的DOM: 会产生错误DOM更新 ==> 界面有问题。
- 如果没有手动绑定key,vue会默认把索引值index作为唯一标识 4.使用id作为key:
5.开发中如何选择key?
- 最好使用每条数据的唯一标识作为key, 比如id、手机号、身份证号、学号等唯一值。
- 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
12.3 列表过滤案例
<div id="root">
<h2>人员列表</h2>
<input type="text" placeholder="请输入名字" v-model="keyWord">
<ul>
<li v-for="(p,index) of filPerons" :key="index">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
用watch方法实现
new Vue({
el:'#root',
data:{
keyWord:'',
persons:[
{id:'001',name:'马冬梅',age:19,sex:'女'},
{id:'002',name:'周冬雨',age:20,sex:'女'},
{id:'003',name:'周杰伦',age:21,sex:'男'},
{id:'004',name:'温兆伦',age:22,sex:'男'}
],
filPerons:[]
},
watch:{
keyWord:{
immediate:true,
handler(val){
//filter()方法:创建一个新的数组,新数组中的元素是通过查询指定数组中符合条件的所有元素。
this.filPerons = this.persons.filter((p)=>{
//注意:indexOf()结果不存在返回-1,但查询一个空字符串返回结果为0不是-1
return p.name.indexOf(val) !== -1
})
}
}
}
})
用computed方法实现(更简洁)
new Vue({
el:'#root',
data:{
keyWord:'',
persons:[
{id:'001',name:'马冬梅',age:19,sex:'女'},
{id:'002',name:'周冬雨',age:20,sex:'女'},
{id:'003',name:'周杰伦',age:21,sex:'男'},
{id:'004',name:'温兆伦',age:22,sex:'男'}
],
},
computed:{
filPerons(){
//计算属性第一次读取时会执行一次 此时indexOf('')传入为空字符串,会渲染全部数据
return this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1
})
}
}
})