目录
一、绑定class样式与绑定style样式
绑定样式:
1.class样式
写法::class = "xxx" xxx可以是字符串、对象、数组
字符串写法适用于:类名不确定、要动态获取。
数组写法适用于:要绑定多个样式,个数不确定,名字也不确定
<!-- 准备好一个容器 -->
<div id="root">
<!-- 数组写法 -->
<div class="basic" :class="classArr">{{name}}</div>
</div>
<script type="text/javascript">
new Vue({
el: '#root',
data: {
name: '山龟骨',
classArr: ['atguigu1', 'atguigu2', 'atguigu3']
},
})
</script>
对象写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。用就将其该对象中的该类名的属性值设置为 true
<div id="root">
<!-- 对象写法 -->
<div class="basic" :class="classObj">{{name}}</div>
</div>
<script type="text/javascript">
new Vue({
el: '#root',
data: {
name: '山龟骨',
classObj: {
atguigu1: false,
atguigu2: true,
atguigu3: false,
}
},
})
</script>
2. style样式
:style = "{fontSize: xxx}",对象的写法, 其中xxx是动态值,xxx交给了Vue管理,注意样式使用小驼峰,且将其放在一个对象中
<!-- 准备好一个容器 -->
<div id="root">
<!-- 对象写法 -->
<div class="basic" :style="{fontSize: fsize + 'px'}">{{name}}</div>
<div class="basic" :style="styleObj">{{name}}</div>
</div>
<script type="text/javascript">
new Vue({
el: '#root',
data: {
name: '山龟骨',
fsize: 30,
styleObj: {
fontSize: '40px',
color: 'red',
backgroundColor: 'orange'
}
},
})
</script>
:style = "[a,b]" 其中a、b是样式对象 ,数组写法,比较少见
<div id="root">
<div class="basic" :style="[styleObj,styleObj2]">{{name}}</div>
<!-- 或者 -->
<div class="basic" :style="styleArr">{{name}}</div>
</div>
<script type="text/javascript">
new Vue({
el: '#root',
data: {
name: '山龟骨',
styleObj: {
fontSize: '40px',
color: 'red',
},
styleObj2: {
backgroundColor: 'orange'
},
styleArr: [
{
fontSize: '40px',
color: 'red',
},
{
backgroundColor: 'orange'
}
]
},
})
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>document</title>
<style>
.basic{
width: 400px;
height: 100px;
border: 1px solid black;
}
.happy{
background-color: red;
}
.sad{
background-color: gray;
}
.normal{
background-color: skyblue;
}
.atguigu1{
background-color: greenyellow;
}
.atguigu2{
font-size:30px;
}
.atguigu3{
border-radius: 0.5cm;
}
</style>
<!-- <script type="text/javascript" src="../script/vue.js"></script> -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
<!-- 绑定class样式 --字符串写法,适用于:要绑定的样式个数不确定、名字也不确定 -->
<div class="basic" :class="mood" @click="changeMood">{{name}}</div><br>
<!-- 绑定class样式 --数组写法,适用于:样式的类名不确定,需要动态指定 -->
<div class="basic" :class="classArr">{{name}}</div>
<!-- 绑定class样式 --对象写法,适用于:要绑定的样式的个数确定、名字也确定,
但要动态决定用不用 -->
<div class="basic" :class="classObj">{{name}}</div><br>
<!-- 绑定style样式 --对象写法 -->
<div class="basic" :style="styleObj">{{name}}</div><br>
<!-- 绑定style样式 --数组写法 -->
<div class="basic" :style="[styleObj,styleObj2]">{{name}}</div>
<!-- 绑定style样式 --数组写法 -->
<div class="basic" :style="styleArr">{{name}}</div>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
name:'尚硅谷',
mood:'normal',
classArr:['atguigu1','atguigu2','atguigu3'],
classObj:{
atguigu1:false,
atguigu2:false,
},
styleObj:{
fontSize:'40px',
color:'red',
},
styleObj2:{
backgroundColor:'orange'//两个单词注意要写成驼峰写法
},
styleArr:[
{
fontSize:'40px',
color:'blue',
},
{
backgroundColor:'gray'
}
]
},
methods:{
changeMood(){
const arr = ['happy','sad','normal']
const index = Math.floor(Math.random()*3)
this.mood = arr[index]
}
}
})
</script>
</html>
二、条件渲染
v-show和v-if的区别——高频面试题
1. v-if
写法:(1). v-if = "表达式"
(2). v-else-if = "表达式"
(3). v-else 后面不用跟表达式
适用于:切换频率较低的场景
特点:不展示的DOM元素直接被移除,比较耗性能
注意:v-if 可以和: v-else-if、v-else一起使用,但要求结构不能被“打断”。就是中间不能插入别的代码语句
<div id="root">
<!-- 需求: n=1时展示一个div,等于2再展示一个div -->
<h2>当前的n值是:{{n}}</h2>
<button @click="n++">点我n++</button>
<div v-if="n === 1">Angular</div>
<div v-else-if="n === 2">react</div>
<div v-else-if="n === 3">Vue</div>
<div v-else>hhh</div> // v-else 后面不用跟表达式
</div>
<script type="text/javascript">
new Vue({
el: '#root',
data: {
n: 0
},
})
</script>
2.v- show
写法:v-show="表达式"
适用于:切换频率较高的场景,
特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉,本质为其添加了内联样式display:none
3.备注:使用v-if时,元素可能无法获取到,而使用v-show元素一定可以获取到。
template 标签模板,最大的特点是不影响结构,只能与v-if配合使用
写结构的时候,可以使用 template进行包裹,页面渲染时 template不存在
<div id="root">
<h2>当前的n值是:{{n}}</h2>
<button @click="n++">点我n++</button>
<!-- 当n=1时,三个div全展示 -->
<!-- 下面写比较麻烦 -->
<!-- <h2 v-show="n===1">你好</h2>
<h2 v-show="n===1">尚硅谷</h2>
<h2 v-show="n===1">背景</h2> -->
<!-- 下面这样写简单,但是破坏了结构 -->
<!-- <div v-show="n===1">
<h2>你好</h2>
<h2>山龟骨</h2>
<h2>背景</h2>
</div> -->
<!-- 使用template标签包裹,不会破坏结构,但只能配合v-if使用 -->
<template v-if="n===1">
<h2>你好</h2>
<h2>山龟骨</h2>
<h2>背景</h2>
</template>
</div>
<script type="text/javascript">
new Vue({
el: '#root',
data: {
n: 0
},
})
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
<h2>当前的n值是:{{n}}</h2>
<button @click="n++">点我n+1</button>
<!-- 使用v-show做条件渲染,是否隐藏 -->
<!-- <h2 v-show="false">欢迎来到{{name}}</h2> -->
<!-- <h2 v-show="1===2">欢迎来到{{name}}</h2> -->
<!-- 使用v-if做条件渲染,确定是否隐藏,并直接将该结构去除了,所以比较耗性能 -->
<!-- <h2 v-if="false">欢迎来到{{name}}</h2> -->
<!-- <h2 v-if="1===2">欢迎来到{{name}}</h2> -->
<!-- <div v-show="n === 1">Angular</div>
<div v-show="n === 2">React</div>
<div v-show="n === 3">Vue</div> -->
<!-- v-else 和 v-else-if -->
<!-- <div v-if="n === 1">Angular</div>
<div v-else-if="n === 2">React</div>
<div v-else-if="n === 3">Vue</div>
<div v-else>'哈哈'</div> -->
<!-- template模板,最大的特点是不影响结构,只能与v-if配合使用 -->
<template v-if="n===1">
<h2>北京</h2>
<h2>你好</h2>
<h2>尚硅谷</h2>
</template>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
name:'尚硅谷',
n:0,
}
})
</script>
</html>
三、列表渲染
v-for指令
1.用于展示列表数据
2.语法:v-for="(item,index) in xxx " :key="yyy",保证遍历列表数据得到的元素的key不相同即可,所以yyy 可以使用 item.id 或者 index
3.可遍历:数组、对象、字符串(用得很少)、指定次数(用得很少)
想生成多个谁,就在谁身上用 v- for指令,就可以生成对应数量的该元素
插值语法中的表达式里面的变量有三个来源:1. data中的属性, 2.计算属性中的属性,3. 标签中的形参
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>document</title>
<!-- <script type="text/javascript" src="../script/vue.js"></script> -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
<!-- 遍历数组 -->
<h2>人员列表(遍历数组)</h2>
<ul>
<!-- 保证该ul中每个人的key是不一样的就可,一般两种写法
1.:key="p.id"
2.:key="index" -->
<li v-for="(p,index) in persons" :key="p.id">
{{p.name}}-{{p.age}}
</li>
</ul>
<!-- 遍历对象 -->
<h2>汽车信息(遍历对象)</h2>
<ul>
<li v-for="(value,k) in car" :key="k">
{{k}}--{{value}}
</li>
</ul>
<!-- 遍历字符串 -->
<h2>测试遍历字符串(用得少)</h2>
<ul>
<li v-for="(char,index) in str" :key="index">
{{char}}--{{index}}
</li>
</ul>
<!-- 遍历指定次数 -->
<h2>测试遍历指定次数(用得少)</h2>
<ul>
<li v-for="(number,index) in 5" :key="index">
{{number}}--{{index}}
</li>
</ul>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
persons:[
{id:'001',name:'张三',age:18},
{id:'002',name:'李四',age:19},
{id:'003',name:'王五',age:20}
],
car:{
name:'奥迪A8',
price:'70万',
color:'黑色'
},
str:'hello'
}
})
</script>
</html>
四、key作用与原理
面试题: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 可能会引发的问题:
(1). 若对数据进行: 逆序添加、逆序删除等破坏顺序操作:
会产生没有必要的真实DOM更新 ==> 界面效果没问题,但效率低。
(2).如果结构中还包含输入类的DOM(如input框):
会产生错误DOM更新 ==> 界面有问题。
4.开发中如何选择key?
(1). 最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
(2).如果不存在对数据的逆序添加、逆序删除等破坏性操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
<h2>人员列表(遍历数组)</h2>
<button @click.once="add">添加一个老刘</button>
<ul>
<li v-for="(p,index) in persons" :key="p.id">
{{p.name}}-{{p.age}}
<input type="text">
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
persons:[
{id:'001',name:'张三',age:18},
{id:'002',name:'李四',age:19},
{id:'003',name:'王五',age:20}
],
},
methods:{
add(){
const p = {id:'004',name:'老刘',age:40};
this.persons.unshift(p);
}
},
})
</script>
</body>
</html>
五、列表过滤(使用监视实现,使用计算属性实现(更方便)
1.使用监视属性实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
<h2>人员列表(遍历数组)</h2>
<!-- 收集用户的输入 -->
<input type="text" placeholder="请输入名字" v-model="keyWord">
<ul>
<li v-for="(p,index) in filPersons" :key="index">
{{p.name}}-{{p.age}}--{{p.gender}}
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
keyWord:'',
persons:[
{id:'001',name:'马冬梅',age:18,gender:'女'},
{id:'002',name:'周冬雨',age:19,gender:'女'},
{id:'003',name:'周杰伦',age:20,gender:'男'},
{id:'004',name:'温兆伦',age:21,gender:'男'}
],
filPersons:[]
},
/* watch:{
keyWord(val){
this.filPersons = this.persons.filter((p)=>{
// indexOf方法判断一个字符串是否包含指定内容,包含返回其索引位置,不包含返回-1
return p.name.indexOf(val) !== -1
})
}
} */
watch:{
keyWord:{
immediate:true,
handler(val){
this.filPersons = this.persons.filter((p)=>{
return p.name.indexOf(val) != -1
})
}
}
}
})
</script>
</body>
</html>
2.使用计算属性实现(更方便)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
<h2>人员列表(遍历数组)</h2>
<!-- 收集用户的输入 -->
<input type="text" placeholder="请输入名字" v-model="keyWord">
<ul>
<li v-for="(p,index) in filPersons" :key="p.id">
<!--注意key要使用p.id更好,因为整个操作一直是对列表进行修改-->
{{p.name}}-{{p.age}}--{{p.gender}}
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
keyWord:'',
persons:[
{id:'001',name:'马冬梅',age:18,gender:'女'},
{id:'002',name:'周冬雨',age:19,gender:'女'},
{id:'003',name:'周杰伦',age:20,gender:'男'},
{id:'004',name:'温兆伦',age:21,gender:'男'}
],
},
computed:{
filPersons(){
return this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1
})
}
}
})
</script>
</body>
</html>
当代码被注释后,在注释代码的下面写新代码,那么被注释的代码无法被折叠,在想折叠的代码上方写#region 想折叠的代码的下方写#endregion
六、列表排序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="root">
<h2>人员列表(遍历数组)</h2>
<!-- 收集用户的输入 -->
<input type="text" 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="p.id">
{{p.name}}-{{p.age}}--{{p.gender}}
</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
keyWord:'',
persons:[
{id:'001',name:'马冬梅',age:30,gender:'女'},
{id:'002',name:'周冬雨',age:19,gender:'女'},
{id:'003',name:'周杰伦',age:35,gender:'男'},
{id:'004',name:'温兆伦',age:50,gender:'男'}
],
sortType:0,//0代表原顺序,1代表降序,2升序
},
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>
</html>