知识点: v-if、v-for、在vue中重写的数组的方法、识别不同的dom节点
v-if
条件渲染有三个: v-if v-else-if v-else,使用方法跟js相似
他们是把多余的dom节点去除(不是none)
<div id="app">
<p v-if='items > 10'>有库存{{ items }}个</p>
<p v-else-if='0<items && items<=10'>即将售馨</p>
<p v-else>没有货啦,下次光临</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
items: 0,
}
})
</script>
template标签
既想使用一个标签包裹需要需要的标签,又不想显示包裹标签,可以使用template标签
v-if == true显示
v-if == false隐藏
<div id="app">
<template v-if="show">
<p>我是第一个P标签</p>
<p>我是第二个P标签</p>
</template>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
show: true,
}
})
</script>
v-show
v-show == true 把dom节点显示
v-show == false 把dom节点隐藏(display:none)
<div id="app">
<button @click = "show = !show">点击显示隐藏</button>
<p v-show = "show">我是用v-shou显示</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
show: true,
}
})
</script>
v-for
v-for的基础使用方法
<div id="app">
<ul>
<li v-for = 'item in movies'>{{ item }}</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
movies: ['扫毒2天地对决', '跳舞吧!大象', '英雄之战', '复仇者联盟4:终局之战']
}
})
</script>
在数组中使用对象增加评分
<div id="app">
<ul>
<li v-for = 'item in movies'>电影名称:{{ item.movie }}|评分:{{ item.rate }}</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
movies: [{
movie: '扫毒2天地对决',
rate: '8.1',
},{
movie: '跳舞吧!大象',
rate: '7.6',
},{
movie: '英雄之战',
rate: '6.4',
},{
movie: '复仇者联盟4:终局之战',
rate: '9.1',
},]
}
})
</script>
索引: 在item中可以分成item和index(自定义)来写
<li v-for = '(item, index) in movies'>{{ index }}|电影名称:{{ item.movie }}|评分:{{ item.rate }}</li>
循环对象
第一个形参: 对象值
第二个形参:对象名
第三个形参: 对象索引
<div id="app">
<p v-for = '(value, prop, index) in person'>{{ index }}|{{ prop }}|{{ value }}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
person: {
name: 'fanghuayong',
age: '18',
sex: '男'
}
}
})
</script>
v-for还可以循环数字和字符
<ul>
<li v-for="num in 10">{{ num }}</li>
</ul>
<p v-for="str in 'fanghuayong'">{{ str }}</p>
v-for在开发中的使用:
通常结合template标签使用,因为template标签不会有dom节点
不能直接改变数组中的数据
有一些重写的方法,如push
:key值告诉模板每隔渲染的不一样
写个需求1:
在使用鼠标点击列表中的电影,电影的名字变成西虹市首富,评分6.5
点击之前
代码:
<div id="app">
<ul>
<li v-for = '(item, index) in movies' @click = 'changeMovie(index)'>{{ index }}|电影名称:{{ item.movie }}|评分:{{ item.rate }}</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
movies: [{
movie: '扫毒2天地对决',
rate: '8.1',
},{
movie: '跳舞吧!大象',
rate: '7.6',
},{
movie: '英雄之战',
rate: '6.4',
},{
movie: '复仇者联盟4:终局之战',
rate: '9.1',
},],
person: {
name: 'fanghuayong',
age: '18',
sex: '男'
}
},
methods: {
changeMovie: function(i){
// 先定位到点击的是哪个li
console.log(i)
this.movies[i] = {
movie: "西虹市首富",
rate: '6.5',
}
console.log(this.movies)
}
}
})
</script>
点击后:
为什么数据发生改变了,内容没有刷新?
在vue中,数组直接改变,不会被检测到,所以也面不会刷新。(因为数组是引用值,新数据和旧数据的内存地址都一样,所以不会发生改变)
那么如何改变数组中的元素?
使用副本 coucat(),改变为新的内存地址,把列表替换到新数组上。(使vue检测到数据发生改动,重新渲染)
// js的vue中的metods字段
methods: {
changeMovie: function(i){
let arr = this.movies.concat()
arr[i] = {
movie: "西虹市首富",
rate: '6.5',
}
this.movies = arr
}
}
dom节点已刷新
需求2: botton按键每点击一下,新增一部电影
<!-- html新增代码 -->
<button @click = "add">新增电影</button>
<!-- js的vue中的metods字段 -->
methods: {
changeMovie: function(i){
let arr = this.movies.concat()
arr[i] = {
movie: "西虹市首富",
rate: '6.5',
}
this.movies = arr
},
add: function() {
this.movies.push({
movie: "东虹市首富",
rate: '6.6',
})
}
}
为什么我们使用push方法新增,并没有改变内存地址,但是刷新dom了呢?(push是数组原型链上的方法)
因为在vue中重写了push()方法,使在使用push()后vue监测到数据发生变化,所以重新渲染了。
备注:vue中重写了push/pop/reverse等方法,大概有六七个,等有时间再看。
让dom节点识别成不同的dom节点
需求: 使input框倒置
<div id="app">
<template v-for = "item in arr">
<p>{{ item }}</p>
<input type="text">
</template>
<button @click = 'reverse'>倒置</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
arr: [1, 2, 3],
},
methods: {
reverse: function() {
this.arr.reverse();
}
}
})
</script>
倒置前:
倒置后:
问题: reverse也是重写的方法,为什么p标签倒置了,input框没有被倒置呢?
渲染机制: 渲染的时候这几个input框没有什么区别,识别的时候也没有什么不同,为了节省资源,没有重排重绘。
解决: 使用v-bind:绑定key,给不同的input框绑定不同的值,这里刚好可以使用循环的item。这样就可以识别成不一样的input。
<input type="text" :key = "item">
倒置前:
倒置后
成功。