本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
Vue学习笔记(第三天)
计算属性
1.姓名案例-插值语法实现
根据之前所学,使用基本的插值语法,通过v-model实现数据与页面展示的双向绑定,即可实现功能
<div id="root">
姓:<input type="text" v-model="firstName"><br><br>
名:<input type="text" v-model="lastName"><br><br>
全名:<span>{{firstName}}-{{lastName}}</span>
</div>
<script type="text/javascript">
new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三'
},
})
</script>
2.姓名案例-methods实现
<div id="root">
姓:<input type="text" v-model="firstName"><br><br>
名:<input type="text" v-model="lastName"><br><br>
全名:<span>{{fullName()}}</span>
</div>
<script type="text/javascript">
new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三'
},
methods: {
fullName() {
return this.firstName + '-' + this.lastName
}
},
})
</script>
3.姓名案例-计算属性实现
计算属性:
- 定义:要用的属性不存在,要通过已有属性计算得来
- 原理:底层借助了Object.defineproperty方法提供的getter和setter
- get函数什么时候执行?
- 初次读取时会执行一次
- 当依赖的数据发生改变时会被再次调用
- 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调用方便
- 备注
- 计算属性最终会出现在vm上,直接读取使用即可
- 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变
<div id="root">
姓:<input type="text" v-model="firstName"><br><br>
名:<input type="text" v-model="lastName"><br><br>
全名:<span>{{fullName}}</span><br><br>
</div>
computed: {//计算属性
fullName: {
// get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
// get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
get() {
console.log('get被调用了')
// console.log(this);
return this.firstName + '-' + this.lastName
},
//set什么时候调用?当fullName被修改时
set(value) {
console.log('set', value)
const arr = value.split('-')
this.firstName = arr[0];
this.lastName = arr[1];
}
}
}
当然计算属性有简写了
// 简写 只有在只考虑读取,不考虑修改的情况下才能简写
fullName() {
console.log('get被调用了')
return this.firstName + '-' + this.lastName
}
监视属性
1.天气案例
没学监视属性时,我们是这样实现的
<div id="root">
<h2>今天天气很{{info}}</h2>
<!-- <button @click="this.isHot = !this.isHot">切换天气</button> -->
<button @click="changeWeather">切换天气</button>
</div>
new Vue({
el: '#root',
data: {
isHot: true
},
methods: {
changeWeather() {
this.isHot = !this.isHot
}
},
computed: {
info() {
return this.isHot ? '炎热' : '凉爽'
}
}
})
2.天气案例-监视属性
监视属性watch:
- 当被监视的属性变化时,回调函数自动调用,进行相关操作
- 监视的属性必须存在,才能进行监视
- 监视的两种写法 (1)new Vue时传入watch配置 (2)通过vm.$watch监视
在上面的基础上,我们进行增加
(1)new Vue时传入watch配置
watch: {
isHot: {
immediate: true,//初始化时让handler调用一下
//handler什么时候调用?当isHot发生修改
handler(newValue, oldValue) {
console.log('isHot被修改了', newValue, oldValue);
}
},
(2)通过vm.$watch监视
vm.$watch('isHot', {
immediate: true,
handler(newValue, oldValue) {
console.log('info被修改了', newValue, oldValue);
}
})
3.天气案例-深度监视
深度监视:
- Vue中的watch默认不监测对象内部值的改变(一层)
- 配置deep:true可以监测对象内部值的改变(多层)
备注:
- Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以
- 使用watch时根据数据的具体结构,决定是否采用深度监视
<div id="root">
<h2>今天天气很{{info}}</h2>
<!-- <button @click="this.isHot = !this.isHot">切换天气</button> -->
<button @click="changeWeather">切换天气</button>
<hr>
<h3>a的值是:{{numbers.a}}</h3>
<button @click="numbers.a++">点我让a+1</button>
<hr>
<h3>b的值是:{{numbers.b}}</h3>
<button @click="numbers.b++">点我让b+1</button>
<button @click="numbers={a:666,b:888}">彻底替换掉numbers</button>
</div>
深度监视的两种简写形式如下
4.姓名案例-watch实现
computed 和 watch之间的区别:
- computed能完成的功能,watch都可以完成
- watch能完成的功能,computed不一定能完成,例如watch可以进行异步操作
两个重要的小原则:
- 所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象
- 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等),最好写成箭头函数。这样this的指向才是vm或组件实例对象
<div id="root">
姓:<input type="text" v-model="firstName"><br><br>
名:<input type="text" v-model="lastName"><br><br>
全名:<span>{{fullName}}</span><br><br>
</div>
watch: {
firstName(val) {
//箭头函数特点:本身不存在this,但是可以通过调用上下域中的this供自己使用
setTimeout(() => {
this.fullName = val + '-' + this.lastName
}, 1000)
},
lastName(val) {
this.fullName = this.firstName + '-' + val
}
}
绑定样式
在已有多个样式的基础上,进行样式的绑定
<!-- 绑定class样式--字符串写法 适用于:样式的类名不确定,需要动态绑定-->
<div class="basic" :class="mood" @click="changeMood">{{name}}</div>
<!-- 绑定class样式--数组写法 适用于:要绑定的样式个数不确定、名字也不确定-->
<div class="basic" :class="classArr">{{name}}</div>
<!-- 绑定class样式--对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用 -->
<div class="basic" :class="classObj">{{name}}</div>
<!-- 绑定style样式--对象写法-->
<div class="basic" :style="styleObj">{{name}}</div>
<!-- 绑定style样式--数组写法-->
<div class="basic" :style="[styleObj,styleObj2]">{{name}}</div>
data: {
name: 'hhh',
mood: 'normal',
classArr: ['hh1', 'hh2', 'hh3'],
classObj: {
hh1: false,
hh2: false
},
styleObj: {
fontSize: '40px',
color: 'red',
},
styleObj2: {
backgroundColor: 'orange'
},
},
条件渲染
1.v-if
写法:
(1)v-if="表达式"
(2)v-else-if="表达式"
(3)v-else="表达式"
适用于:切换频率较低的场景
特点:不展示的DOM元素直接被移除
注意:v-if可以和v-else-if、v-else一起使用,但要求结构不能被“打断”
2.v-show
写法:v-show="表达式"
适用于:切换频率较高的场景
特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
3.备注:使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到
<div id="root">
<h2>当前的n值是:{{n}}</h2>
<button @click="n++">点我+1</button>
<!-- 使用v-show做条件渲染 -->
<!-- <h2 v-show="a">欢迎来到{{name}}</h2>
<h2 v-show="true">欢迎来到{{name}}</h2>
<h2 v-show="1===1">欢迎来到{{name}}</h2> -->
<!-- 使用v-if做条件渲染 -->
<!-- <h2 v-if="1===1">欢迎来到{{name}}</h2>
<h2 v-if="true">欢迎来到{{name}}</h2> -->
<!-- <div v-show="n===1">Angular</div>
<div v-show="n===1">React</div>
<div v-show="n===3">Vue</div> -->
<!-- <div v-if="n===1">Angular</div>
<div v-if="n===1">React</div>
<div v-if="n===3">Vue</div> -->
<!-- <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> -->
<!-- v-if与templated的配合使用 -->
<template v-if="n===1">
<h2>你好</h2>
<h2>!!</h2>
<h2>北京</h2>
</template>
</div>
new Vue({
el: '#root',
data: {
name: '学校',
a: true,
n: 0
},
})