一、监视属性
1、通过methods和computed实现属性变化
@XXX='XXX'中可以写一些简单的语句
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="isHot = !isHot">切换天气</button>
<button @click="changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
isHot: true
},
computed: {
info: {
get() {
return this.isHot ? '炎热' : '凉爽';
},
set(value) {
}
}
},
methods: {
changeWeather() {
this.isHot = !this.isHot;
}
}
})
</script>
2、watch方法
1)isHot发生变化时,会调用handler方法
2)immediate,在初始化时让handler调用
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="isHot = !isHot">切换天气</button>
<button @click="changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
isHot: true
},
computed: {
info: {
get() {
return this.isHot ? '炎热' : '凉爽';
},
set(value) {
}
}
},
methods: {
changeWeather() {
this.isHot = !this.isHot;
}
},
watch: {
isHot: {
immediate: true,
handler(newValue, oldValue) {
console.log("isHot被改动", newValue, oldValue);
}
},
info: {
immediate: true,
handler(newValue, oldValue) {
console.log("info被改动", newValue, oldValue);
}
}
}
})
3) watch的第二种写法,使用$watch
const vm = new Vue({
el: '#root',
data: {
isHot: true
},
computed: {
info: {
get() {
return this.isHot ? '炎热' : '凉爽';
},
set(value) {
}
}
},
methods: {
changeWeather() {
this.isHot = !this.isHot;
}
}
})
vm.$watch('info', {
immediate: true,
handler(newValue, oldValue) {
console.log("info被改动", newValue, oldValue);
}
})
3、深度监视
1)Vue是可以监测对象内部值的改变的,但watch默认不监测对象内部值的改变(一层),这是为了提高效率
2)配置deep:true可以监测象内部值的改变(多层)
<body>
<div id="root">
<h3>a的值是:{{numbers.a}}</h3>
<button @click="numbers.a++">点击让a+1</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
numbers: {
a: 1,
b: 1
}
},
watch: {
// 如果只监视a,可以这么写
'numbers.a': {
immediate: true,
handler(newValue, oldValue) {
console.log("a被改动", newValue, oldValue);
}
},
// 如果要监视number中任意属性的变化,就要开启深度监视
numbers: {
deep: true,
handler(newValue, oldValue) {
console.log("number被改动", newValue.a, oldValue);
}
}
}
})
</script>
4、computed和watch的区别
- computed能完成的功能,watch都能完成
- watch能完成的功能,computed不一定能完成,例如watch可以进行异步操作
两个要注意的原则
- 所有被Vue管理的函数,都不要写箭头函数,这样this指向才是vm
- 所有不被Vue管理的函数,如定时器的回调函数、ajax的回调函数等,都要写箭头函数,这样this指向才是vm
<body>
<div id="root">
姓:<input type="text" v-model="firstName"><br><br>
名:<input type="text" v-model="secondName"><br><br>
全名:<span>{{fullName}}</span><br><br>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
firstName: '张',
secondName: '三',
fullName: '张-三'
},
watch: {
firstName(val) {
this.fullName = val + "_" + this.secondName;
},
secondName(val) {
this.fullName = this.firstName + "_" + val;
}
}
})
二、绑定class样式
通过:class,:style指定样式名,通过更改data中的属性值达到更改样式的效果
<body>
<div id="root">
<div :class="myClass" @click="changeMood">test</div> <br> <br>
<div :style="{fontSize: fSize + 'px'}" @click="changeFont">test</div> <br> <br>
<div :style="myStyle" @click="changeStyle">test</div> <br> <br>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
myClass: 'red',
fSize: '30',
myStyle: {
fontSize: '30px',
color: 'blue'
}
},
methods: {
changeMood() {
this.myClass = 'green';
},
changeFont() {
this.fSize = 50;
},
changeStyle() {
this.myStyle.color = 'pink';
}
}
})
</script>
三、条件渲染
1、v-show与v-if
通过v-show或v-if来做条件渲染
2、v-if与v-else-if与v-else
注意,这3种标签之间不能中断,必须连续
<body>
<div id="root">
<h2 v-show="show">欢迎,{{name}}</h2>
<h2 v-if="show">欢迎,{{name}}</h2>
<h2 v-if="a === 1">1</h2>
<h2 v-else-if="a === 2">2</h2>
<h2 v-else-if="a === 3">3</h2>
<h2 v-else>4</h2>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
show: true,
name: '高大俊',
a: 2
}
})
</script>
v-show和v-if二者的区别,v-show是添加display样式,v-if是直接注释掉代码
3、v-if与template配合使用
<template v-if="a === 1">
<h2>A</h2>
<h2>B</h2>
</template>
四、列表渲染
1、基本列表
使用v-for遍历数组或对象,用于展示数据
<body>
<div id="root">
<h2>人员列表1(遍历数组)</h2>
<ul>
<li v-for="p in persons" :key="p.id">
姓名:{{p.name}},年龄:{{p.age}}
</li>
</ul>
<h2>人员列表2(遍历数组)</h2>
<ul>
<li v-for="(p,index) in persons" :key="p.id">
姓名:{{p.name}},年龄:{{p.age}},序号:{{index}}
</li>
</ul>
<h2>汽车信息(遍历对象)</h2>
<ul>
<li v-for="(value,index) in car" :key="index">
{{index}}:{{value}}
</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:'黑色'
}
}
})
</script>
2、key的原理
1)生成初始数据,并在v-for遍历时,使用index作为key值
2)vue根据数据生成虚拟DOM,写入内存
3)vue将虚拟DOM转成真实DOM,也就是我们在页面上能看到的
4)生成了新数据,vue根据新数据生成虚拟DOM
5)将新生成的虚拟DOM和原来的虚拟DOM中,key相同的进行对比
6)对比时发现,key等于0的数据行中,张三和老刘这2个字段不匹配,input标签数据匹配,所以将老刘替换成原来的张三,input因为匹配所以不变动。key等于1、2、3的也同样操作,所以会发生页面上input框错乱的问题
用index作为key时,在对数据进行添加、删除时,会出现问题。当没有指明key时,vue会默认使用index来作为key。因此必须要使用唯一标识来作为key
3、列表过滤
1)使用watch来实现对列表的过滤
<body>
<div id="root">
<h2>人员列表</h2>
<input type="text" placeholder="请输入名字" v-model="keyWord">
<ul>
<li v-for="p in newPersons" :key="p.id">
姓名:{{p.name}},年龄:{{p.age}}
</li>
</ul>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = 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:'女'},
{id:'004',name:'温兆伦',age:21,sex:'男'}
],
newPersons:[]
},
watch: {
keyWord:{
immediate: true,
handler(val) {
this.newPersons = this.persons.filter((p) => {
return p.name.indexOf(val) > -1;
})
}
}
}
})
</script>
2)用computed实现
// 用computed实现
const vm = 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:'女'},
{id:'004',name:'温兆伦',age:21,sex:'男'}
]
},
computed: {
newPersons() {
return this.persons.filter((p) => {
return p.name.indexOf(this.keyWord) > -1;
})
}
}
})
4、列表排序
<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 in newPersons" :key="p.id">
姓名:{{p.name}},年龄:{{p.age}}
</li>
</ul>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
keyWord:'',
sortType: 0, // 0:原顺序,1:降序,2:升序
persons: [
{id:'001',name:'马冬梅',age:18,sex:'女'},
{id:'002',name:'周杰伦',age:19,sex:'男'},
{id:'003',name:'周冬雨',age:20,sex:'女'},
{id:'004',name:'温兆伦',age:21,sex:'男'}
]
},
computed: {
newPersons() {
const arrs = this.persons.filter((p) => {
return p.name.indexOf(this.keyWord) > -1;
});
if (this.sortType == 0) {
return arrs;
} else {
arrs.sort((a,b) => {
return this.sortType == 1 ? b.age - a.age : a.age - b.age
});
return arrs;
}
}
}
})
</script>