计算属性
基本类似于方法,但是他使用 get 获取到对象,以下为代码解析步骤
- 设置计算属性 fullName,并为其设置一个 get 方法
- 在 get 方法里面的 this 依旧指向当前的 vue 实例
- 调用计算属性和调用 data 属性是一样的,都可以直接使用插值语法
<body>
<div class="root">
<div>{{fullName}}</div>
</div>
</body>
<script>
computed:{
fullName:{
get(){
console.log(this.name)
return this.name
},
set(val){
console.log(val)
}
}
}
</script>
getter setter 方法解析
- 当有人读取 fullName 时,get 方法被调用,get 中 return 的值就作为 fullName 的值
- get 方法在初次调用后如果 fullName 的值没有变动,则后续调用都无效,直到 fullName 的值发生变化
- 当 fullName 的值被修改时调用 set 方法
计算属性的简写
不把计算属性作为对象写,直接把他当做一个方法来写
- 这样做将只有 getter 属性而无法写 setter 属性
- 同样的,别用箭头函数,不然导致 this 指向错误
- 调用时同理,也是有参数加括号没参数只写名字
<body>
<div class="root">
<div>{{only}}</div>
</div>
</body>
<script>
computed:{
only(){
console.log(this)
return this.name
}
}
</script>
监视属性
即对 data 中的某项属性变化进行实时监控,已下方代码为例
- val 表示欲监听的属性
- handler 表示监听句柄,我们指定的两个形参默认含义为改变后的值和原来的值
- handler 里面写变化后需要执行的代码
- immediate 该参数默认为 false,如果设置为 true 表示一启动页面就开始监听
<script>
data:{
val:false
},
watch:{
val:{
handler(newVal,oldVal){
console.log('内容已经修改',newVal,oldVal)
}
}
}
</script>
另一种直接使用 vue 实例进行监视的方式
<script>
v.$watch("val", {
immediate: false,
handler(n, o) {
console.log(n, o);
},
});
</script>
深层次监视
监视 data 中的多层结构时,使用单引号括起来就可以针对性的监听结构中的某一个属性了
假设我们需要监听一个对象下面的所有属性,那么就需要在监视属性中写入 deep:true 来执行深层次监视
<script>
data: {
numbers:{
a:1,
b:2
}
},
watch:{
'numbers.a':{
handler(){
console.log('a正在发生改变')
}
},
numbers:{
deep:true, // 执行深层次监视
handler(){
console.log('123')
}
}
}
</script>
监视的简写形式
使用这种办法将无法设置 deep 和 immediate 这两个属性,但是 handler 的属性以及形参的含义没有变化
<script>
watch:{
num1(newVal,oldVal){
console.log(newVal,oldVal)
}
}
<!-- 特别注意,下面代码是写在vue实例外面的!!! -->
v.$watch('num2',function(newVal,oldVal){
console.log('123')
})
</script>
watch 和 computed 区别
- watch 可以实现异步回调,到那时 computed 不可以
- 所有被 vue 管理的函数最好使用普通函数,此时 this 指向的才是 vue 实例对象
- 不被 vue 管理的函数(如定时器和 ajax 异步)最好写箭头函数,这样才可以保证 this 指向 vue 实例
绑定 class 和 style 样式
- 绑定 class 就是在 data 域中新建一个属性,并将该属性命名为欲绑定的类的名称,然后于元素中使用 v-bind 绑定
- 注意,第一个 class 绑定后面跟着的:class 是 v-bind 的形式,表示附加的 class,千万不可以少了冒号!
- 有三种绑定方式,字符串型、数组型、对象型,其中数组和对象型可以通过 method 方法动态更改样式的启用与否
<style>
.standard {
height: 100px;
}
.normal {
margin: 100px;
}
</style>
<div class="root">
<div class="height" :class="bind_class">我将具有两个css样式</div>
</div>
<script>
const v = new Vue({
data: {
// 字符串绑定
bind_class: "normal",
// 数组型绑定
bind_arr: ["standard", "normal"],
// 对象型绑定
bind_obj: {
standard: true,
normal: false,
},
},
});
</script>
直接于标签内使用数组绑定 class
如题,数组内可以使用三元运算符来判断启用那个样式(isActive 为一个开关)
<div :class="[isActive ? activeClass : '', errorClass]"></div>
绑定 style 样式
类似内联样式表,data 中使用对象存储样式信息然后于 style 内调用该对象启用样式
<div :style="styleObject"></div>
<script>
data() {
return {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
}
</script>
条件渲染
- v-show 接收一个布尔值,它类似于 display 属性,可以显示或者隐藏元素,但是该元素仍然存在
v-if 也接收一个布尔值,但是只要取值为 false,那么它对应的元素将不被创建 - v-if v-else-if v-else 是一组使用的,也就是他们必须要相邻!他们一连串判断下去
<div v-show="false"></div>
<div v-if="true"></div>
<div v-if="1"></div>
<div v-else-if="1"></div>
<div v-else="1"></div>
v-if 最好喝 template 结合在一起使用,这样子就可以实现符合条件则显示或者隐藏一堆元素的办法了!
<template v-if="1==1">
<div></div>
</template>
列表渲染
- 普通列表渲染使用 v-for,且 v-key 表示制定遍历索引,他必须要写
- (p, index) in persons 表示以 index 为索引,p 为值的遍历,遍历的对象是 persons 数组
- 注意我们这里的 index 是默认值,我们可以把它改成 p.id 好让索引以我们设置好的参数来遍历!
- 遍历代码中的 in 可以改为 of
<ul>
<li v-for="(p, index) in persons" :key="index">{{p.name}}</li>
</ul>
<script>
persons: [
{ id: "001", name: "张三" },
{ id: "002", name: "李四" },
{ id: "003", name: "王五" },
];
</script>
还有一个次数渲染,of 后面接着需要遍历的次数即可,前面的括号就写 data 域中定义的属性
<ul>
<li v-for="(a,b) of 10">{{a}}+{{b}}</li>
</ul>
key 有啥用
虚拟 DOM 中 key 的作用:
key 是虚拟 DoM 对象的标识,当数据发生变化时,Vue 会根据【新数据】生成【新的虚拟 DoM】
随后 Vue 进行【新虚拟 DoM】与【I 旧虚拟 DoM】的差异比较
用 index 作为 key 可能会引发的问题:
- 若对数据进行:逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实 D0M 更新=>界面效果没问题,但效率低。
- 如果结构中还包含输入类的 D0M:会产生错误 D0M 更新==>界面有问题
开发中如何选择 key?
- 最好使用每条数据的唯一标识作为 key,比如 id、手机号、身份证号、学号等唯一值
- 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用 index 作为 key 是没有问题的。
列表过滤
使用计算属性来对对象数组执行过滤操作
- 首先创建对象数组 persons,以及属性 keywords 并将其 v-model 到外部的 input 元素上
- 使用列表渲染,并将渲染对象指定为计算属性 filpersons 而不是对象数组 persons
- filpersons 函数中的第一个 return 返回的是一个已经被过滤后的对象数组,this.persons.filter 表示此次过滤是针对 persons 数组的!
- filpersons 函数中的第二个 return 返回过滤条件,这里设置为检测 keywords 里面的值,若该值属于 persons 数组中的任意对象下的 name 属性的一部分,那么返回真
- filter 接收一个箭头函数,该函数返回一个布尔值,他对对象函数内所有对象进行判断,如果 return 的是真,那么就返回符合该条件的对象!!!(有抽象,具体理解)
<body>
<div id="root">
<h2>人员列表</h2>
<input type="text" placeholder="请输入搜索值" v-model="keywords" />
<ul>
<li v-for="(p, index) in filpersons" :key="index">
{{p.name}}-{{p.age}}
</li>
</ul>
</div>
</body>
<script>
new Vue({
el: "#root",
data: {
keywords: "",
persons: [
{ id: "001", name: "王小曼", age: 22 },
{ id: "002", name: "王五", age: 21 },
{ id: "003", name: "无名氏", age: 42 },
{ id: "004", name: "张三", age: 12 },
{ id: "005", name: "李四", age: 35 },
],
},
computed: {
filpersons() {
return this.persons.filter((p) => {
return p.name.indexOf(this.keywords) !== -1;
});
},
},
});
</script>