目录
1.template标签
2.条件渲染
3.列表渲染
4.v-for中的key的作用以及原理
5.列表过滤
placeholder
前端空字符串
使用数据监视watch实现
使用计算属性实现
6.列表排序
7.Vue更新数据检测失败
原因
总结
1.template标签
template标签是Vue.js中的一个特殊元素,它的作用是在渲染过程中作为一个容器,可以承载多个子元素,但不会在最终渲染的DOM中显示。它是Vue.js提供的一种逻辑组织的方式。
template标签可以用来:
-
组织代码:当需要在一个组件或者模板中定义多个子元素时,可以使用template标签将它们包裹起来,提高代码的可读性和组织结构。
-
条件渲染:template标签可以作为条件渲染的容器,根据条件展示不同的内容。
-
循环渲染:template标签可以配合v-for指令,循环渲染一段代码片段多次。
-
提高性能:当组件需要有多个根元素时,可以使用template标签作为一个根元素的容器,避免在渲染的DOM中增加额外的层级。
总之,template标签在Vue.js中起到了一个逻辑组织和代码承载的作用,可以提高代码的可读性和组织结构,并且在渲染过程中不会在最终的DOM中显示。
2.条件渲染
在Vue中,条件渲染是指根据某个条件来决定是否渲染或展示某个元素或组件。Vue提供了两种常用的条件渲染指令:v-show和v-if。
- v-show: v-show是一种基于CSS的条件渲染指令。使用v-show时,元素会始终渲染在DOM中,只是通过CSS的display属性来控制元素的显示和隐藏。
示例:
<div v-show="isVisible">This is a visible element</div>
在上述示例中,当isVisible
为true
时,元素会显示出来;当isVisible
为false
时,元素会隐藏起来。
v-show适用于需要频繁切换元素的显示和隐藏的场景,因为元素始终存在于DOM中,切换过程更加高效。
- v-if: v-if是一种基于DOM的条件渲染指令。使用v-if时,元素会在条件为
true
时渲染到DOM中,条件为false
时,元素会从DOM中移除。
示例:
<div v-if="isVisible">This is a visible element</div>
在上述示例中,当isVisible
为true
时,元素会被渲染到DOM中;当isVisible
为false
时,元素会从DOM中移除。
v-if适用于切换频率较低的场景,因为每次条件变化时,DOM的创建和销毁会有额外的性能开销。
可以使用v-else-if和v-else来串联多个条件。
示例:
<div v-if="condition1">Condition 1 is true</div>
<div v-else-if="condition2">Condition 2 is true</div>
<div v-else>Neither condition is true</div>
在上述示例中,根据条件的不同,会根据条件渲染不同的元素。
总结: v-show通过CSS的display属性控制元素的显示和隐藏,适用于切换频率较高的场景; v-if通过DOM的创建和销毁来控制元素的显示和隐藏,适用于切换频率较低的场景。
代码示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
</head>
<body>
<body>
<div id="root">
<h2>当前的n值是:{{n}}</h2>
<button @click="n++">点我n加一</button>
<button @click="n--">点我n减一</button>
<!-- 使用v-show作条件渲染 -->
<!-- v-show="true":这里为true的时候显示,false的时候不显示 -->
<h1 v-show="false">欢迎来到{{name}}的博客</h1>
<h1 v-show="1 === 3">欢迎来到{{name}}的博客</h1>
<h1 v-show="isTrue">欢迎来到{{name}}的博客</h1>
<br>
<hr>
<br>
<!-- 使用v-if作条件渲染 -->
<h1 v-if="false">欢迎来到{{name}}的博客</h1>
<h1 v-if="1 === 1">欢迎来到{{name}}的博客</h1>
<br>
<hr>
<br>
<!-- 切换比较频繁的时候实用v-show -->
<div v-show="n === 1">机器学习</div>
<div v-show="n === 2">深度学习</div>
<div v-show="n === 3">人工智能</div>
<hr>
<!--
v-else和v-else-if
这几个div要紧紧的连接在一起,中间不能被打断
-->
<div v-if="n === 1">机器学习</div>
<div v-else-if="n === 2">深度学习</div>
<div v-else-if="n === 3">人工智能</div>
<div v-else>哦也</div>
<br>
<hr>
<br>
<!-- 使用此标签可以不修改DOM结构 -->
<!-- 但是只能和v-if配合使用,不能和v-show配合使用 -->
<template v-if="n === 1">
<h2>你好</h2>
<h2>CSDN</h2>
<h2>成都</h2>
</template>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip=false
const vm = new Vue({
el:'#root',
data:{
name:'WenJGo',
isTrue:false,
n:0
}
});
</script>
</html>
页面效果如下图所示:
3.列表渲染
在Vue中,列表渲染是一种常用的功能,用于根据数组或对象的数据生成对应的列表。Vue提供了v-for指令来实现列表渲染。
使用v-for指令,可以通过遍历数组或对象的方式,将每个元素都渲染为对应的DOM元素。
- 遍历数组: 例如,有一个名为
items
的数组,我们可以使用v-for指令来遍历它并渲染为列表:
<ul>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
在上述示例中,v-for="item in items"
表示遍历items
数组,使用item
来表示每个数组元素。:key="item.id"
是为了给每个列表项提供唯一的标识符,用于优化性能。{{ item.name }}
表示渲染每个数组元素的name
属性。
- 遍历对象: 除了遍历数组,我们也可以使用v-for指令来遍历对象的属性。
<ul>
<li v-for="(value, key) in obj" :key="key">{{ key }}: {{ value }}</li>
</ul>
在上述示例中,(value, key) in obj
表示遍历obj
对象的属性,使用value
和key
来表示每个属性的值和键。:key="key"
用于提供唯一的标识符。{{ key }}: {{ value }}
表示渲染每个属性的键和值。
另外,v-for指令还提供了索引值index
,可以在遍历过程中使用。
<ul>
<li v-for="(item, index) in items" :key="item.id">{{ index }} - {{ item.name }}</li>
</ul>
在上述示例中,index
表示当前数组元素的索引值。
总结: 通过v-for指令,我们可以方便地遍历数组和对象,将它们渲染为对应的列表。在处理列表渲染时,我们还可以使用:key
来提供唯一的标识符,优化性能。
总体示例代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title></title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
</head>
<body>
<body>
<div id="root">
<h2>人员列表</h2>
<!-- 遍历数组 -->
<ul>
<!-- :key="per.id"让每一个li都有唯一的标识 -->
<!-- <li v-for="per in personList" :key="per.id"> -->
<li v-for="(per,index) in personList" :key="index">
{{index}}==>{{per.name}}-{{per.age}}
</li>
</ul>
<br>
<hr>
<br>
<!-- 遍历对象 -->
<h2>汽车信息</h2>
<ul>
<li v-for="(value,key) in car" :key="key">
{{key}}:{{value}}
</li>
</ul>
<br>
<hr>
<br>
<!-- 下面的都用得少 -->
<!-- 遍历字符串 -->
<h2>字符串信息</h2>
<ul>
<li v-for="(char,index) in str" :key="key">
{{index}}:{{char}}
</li>
</ul>
<br>
<hr>
<br>
<!-- 遍历指定次数 -->
<h2>遍历指定次数</h2>
<ul>
<li v-for="(times,index) in 5" :key="index" >
{{index}}:{{times}}
</li>
</ul>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip=false
new Vue({
el:'#root',
data:{
// 数组类型
personList:[
{id:'001',name:'张三',age:18},
{id:'002',name:'李四',age:28},
{id:'003',name:'王五',age:22}
],
// 对象类型
car:{
name:'红旗',
price:'1000万',
color:'黑色'
},
// 字符串类型
str:'hello'
}
});
</script>
</html>
4.v-for中的key的作用以及原理
在使用Vue的v-for指令时,可以通过key属性为每个列表项提供一个唯一的标识符。这个key的作用是为Vue跟踪每个列表项的身份,以便在重新渲染列表时,能够高效地更新和重用已有的DOM元素。
当Vue进行列表渲染时,会根据列表数据生成一组对应的DOM元素。当数据发生变化,比如列表项的顺序发生变化、某个列表项被添加或删除时,Vue会基于新的数据重新渲染DOM。这时,Vue会根据每个列表项的key属性来判断该项是否需要重新渲染。
具体原理如下:
-
Vue会根据key属性对每个列表项进行标记,并创建一个列表项到key的映射关系。
-
当数据变化时,Vue会根据新的数据重新计算列表项的顺序。
-
Vue会比较新的列表项顺序和旧的映射关系,找出需要被移动、添加或删除的列表项。
-
对于需要被移动的列表项,Vue会将其从旧的位置移动到新的位置,而不是销毁和重新创建。
-
对于需要被添加的列表项,Vue会根据key属性查找到对应的旧的DOM元素,如果找到了,就将其移动到正确的位置;如果没有找到,才会创建新的DOM元素。
-
对于需要被删除的列表项,Vue会将其从DOM中移除,并在内部进行一些清理工作。
通过使用key属性,Vue能够在列表项发生变化时,快速识别出需要做哪些DOM操作,从而提高性能、减少重绘和重排的开销。
采用index作为key在破坏了原有顺序的情况下(比如插入到最前面)会发生问题,如下图尚硅谷的图片示例所示:
而采用数据本身的id作为key则不会出现上述的问题,如下图尚硅谷的图片所示:
5.列表过滤
placeholder
placeholder属性用于在输入字段中显示提示文本,当输入字段为空时显示。它用于提供关于所需输入的示例或说明。当用户开始输入时,placeholder文本会自动清除或替换为实际输入的内容。这个属性可以帮助用户更好地理解所需输入的格式或类型。
前端空字符串
一个字符串里面一个''空字符串的索引是0,也就是说一个字符串里必然有一个空字符串
使用数据监视watch实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>列表过滤</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
</head>
<body>
<body>
<div id="root">
<h2>人员列表</h2>
<input type="text" placeholder="请输入名字" v-model="keyWord">
<!-- 遍历数组 -->
<ul>
<li v-for="(per,index) in filterPersions" :key="index">
{{index}}==>{{per.name}}-{{per.age}}-{{per.sex}}
</li>
</ul>
<br>
<hr>
<br>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip=false
new Vue({
el:'#root',
data:{
keyWord:'',
// 数组类型
personList:[
{id:'001',name:'马冬梅',age:18,sex:'女'},
{id:'002',name:'周冬雨',age:19,sex:'女'},
{id:'003',name:'周杰伦',age:22,sex:'男'},
{id:'004',name:'温兆伦',age:32,sex:'男'}
],
filterPersions :[]
},
watch:{
keyWord:{
// 加上这个会直接搜索一遍空串,由于都携带空串所以都有了
immediate:true,
handler(newValue){
// console.log('keyWord改为:' + newValue)
this.filterPersions = this.personList.filter((person)=>{
return person.name.indexOf(newValue) !== -1
})
}
}
}
});
</script>
</html>
使用计算属性实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>列表过滤</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
</head>
<body>
<body>
<div id="root">
<h2>人员列表</h2>
<input type="text" placeholder="请输入名字" v-model="keyWord">
<!-- 遍历数组 -->
<ul>
<li v-for="(per,index) in filterPersons" :key="index">
{{index}}==>{{per.name}}-{{per.age}}-{{per.sex}}
</li>
</ul>
<br>
<hr>
<br>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip=false
// 用computed实现
new Vue({
el:'#root',
data:{
keyWord:'',
// 数组类型
personList:[
{id:'001',name:'马冬梅',age:18,sex:'女'},
{id:'002',name:'周冬雨',age:19,sex:'女'},
{id:'003',name:'周杰伦',age:22,sex:'男'},
{id:'004',name:'温兆伦',age:32,sex:'男'}
]
},
computed:{
filterPersons(){
return this.personList.filter((person)=>{
return person.name.indexOf(this.keyWord) !== -1
})
}
}
});
</script>
</html>
6.列表排序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>列表过滤</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
</head>
<body>
<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="(per,index) in filterPersons" :key="index">
{{index}}==>{{per.name}}-{{per.age}}-{{per.sex}}
</li>
</ul>
<br>
<hr>
<br>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip=false
new Vue({
el:'#root',
data:{
keyWord:'',
// 0原顺序,1降序,2升序
sortType:0,
// 数组类型
personList:[
{id:'001',name:'马冬梅',age:28,sex:'女'},
{id:'002',name:'周冬雨',age:19,sex:'女'},
{id:'003',name:'周杰伦',age:22,sex:'男'},
{id:'004',name:'温兆伦',age:32,sex:'男'}
]
},
computed:{
filterPersons(){
// 获取到过滤到的数组
const filArr = this.personList.filter((person)=>{
return person.name.indexOf(this.keyWord) !== -1
})
// 根据排序类型来排序
if(this.sortType !== 0){
filArr.sort((p1,p2)=>{
return this.sortType === 1?p2.age-p1.age:p1.age-p2.age
})
}
return filArr
}
}
});
</script>
</html>
效果如下:
7.Vue更新数据检测失败
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>列表过滤</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
</head>
<body>
<body>
<div id="root">
<h2>人员列表</h2>
<button @click="updateMaDM">更新马冬梅信息</button>
<ul>
<li v-for="(per,index) in personList" :key="per.id">
{{index}}==>{{per.name}}-{{per.age}}-{{per.sex}}
</li>
</ul>
<br>
<hr>
<br>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip=false
const vm = new Vue({
el:'#root',
data:{
// 数组类型
personList:[
{id:'001',name:'马冬梅',age:28,sex:'女'},
{id:'002',name:'周冬雨',age:19,sex:'女'},
{id:'003',name:'周杰伦',age:22,sex:'男'},
{id:'004',name:'温兆伦',age:32,sex:'男'}
]
},
methods: {
updateMaDM(){
/* this.personList[0].name = '马什么梅'
this.personList[0].age = 50
this.personList[0].sex = '男' */
// 出现BUG!!!wdf
this.personList[0] = {
id:'001',
name:'马什么梅',
age:58,
sex:'男'
}
}
},
});
</script>
</html>
这段代码更新的时候发现更新不了。
原因
Vue的响应式系统是基于 JavaScript 的 getter 和 setter 实现的。当 Vue 实例被创建时,Vue 会将 data 中的所有属性转化为 getter 和 setter,以便在属性被访问和修改时能够触发依赖追踪并进行相关的更新。
然而,在我们 的代码中,直接修改了数组中的元素,而并没有调用 Vue 提供的响应式方法来触发更新。
要使 Vue 能够检测到对数组的更改,可以使用 Vue 提供的方法来进行操作。例如,对于这段代码,我们可以使用 Vue.set 或 Vue.$set 方法来修改数组中的元素:
Vue.set(this.personList, 0, {
id: '001',
name: '马什么梅',
age: 58,
sex: '男'
});
// 或者使用 Vue.$set 方法:
this.$set(this.personList, 0, {
id: '001',
name: '马什么梅',
age: 58,
sex: '男'
});
这样做可以通知 Vue 响应式系统进行相应的更新,使得 Vue 能够检测到对数组的更改并进行相应的重新渲染。
总结
条件渲染有两种方法:v-if和v-show。
v-if的写法是v-if="表达式",也可以和v-else-if、v-else一起使用。v-if适用于切换频率较低的场景。它的特点是不展示的DOM元素直接被移除。
v-show的写法是v-show="表达式",它适用于切换频率较高的场景。v-show的特点是不展示的DOM元素未被移除,仅仅是使用样式隐藏掉。
需要注意的是,使用v-if的时候,元素可能无法获取到,而使用v-show则一定可以获取到。
v-for指令
1. 用于展示列表数据
2. 语法:v-for="(item,index) in xxx" :key="yyy"
3. 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
key在虚拟DOM中的作用是为了标识和追踪每个DOM元素的身份。当数据发生变化时,Vue或React会根据新的数据生成新的虚拟DOM,并通过比较新旧虚拟DOM的差异来更新页面的真实DOM。
具体的对比规则如下:
- 如果在新的虚拟DOM中找到了与旧的虚拟DOM相同的key,那么会判断其内容是否有变化。如果内容没有变化,就直接使用之前的真实DOM;如果内容有变化,就生成一个新的真实DOM并替换掉页面中之前的真实DOM。
- 如果在新的虚拟DOM中找不到与旧的虚拟DOM相同的key,就会创建一个新的真实DOM,并将其渲染到页面上。
使用index作为key可能会引发一些问题:
- 如果对数据进行逆序添加、逆序删除等破坏顺序的操作,会导致不必要的真实DOM更新,从而降低性能。
- 如果列表中还包含输入类的DOM,使用index作为key可能会导致错误的DOM更新,从而导致界面问题。
在开发中,应该根据具体情况选择合适的key。最好使用每条数据的唯一标识作为key,比如ID、手机号、身份证号、学号等唯一值。如果仅用于渲染列表展示,并且没有对数据进行逆序添加、逆序删除等破坏顺序的操作,使用index作为key是没有问题的。