1、计算属性
计算属性:顾名思义这个属性是计算出来的,也就是说它并不是我们
data
中定义的。
这里使用使用一个简单的案例来演示,各种形式下的实现形式,进而来展现计算属性的好处
。
1.1、姓名案例-插值语法实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>姓名案例-插值语法实现</title>
<script src="../js/vue.js" type="text/javascript"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName" id=""><br>
名:<input type="text" v-model="lastName" id=""><br>
姓名:<span>{{firstName}}-{{lastName}}</span>
</div>
<script type="text/javascript">
new Vue({
el: '#root',
data () {
return {
firstName: '张',
lastName: '三'
}
},
})
</script>
</body>
</html>
使用最原始方法来实现,使用
双大括号语法
来进行字符的拼接,而且需要注意的是:属性必须用v-model
进行数据的双向绑定。
1.2、姓名案例-method实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>姓名案例-method实现</title>
<script src="../js/vue.js" type="text/javascript"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName" id=""><br>
名:<input type="text" v-model="lastName" id=""><br>
<!-- 在插值语法中使用方法,我们必须给方法加上小括号。但在事件中使用,可以省略(无参数的情况下) -->
姓名:<span>{{fullName()}}</span><br>
</div>
<script type="text/javascript">
new Vue({
el: '#root',
data () {
return {
firstName: '张',
lastName: '三'
}
},
methods: {
// 只要我们的数据发生改变,我们Vue重新解析一遍代码,同时也就是要重新调用一次我们的fullNmae方法
fullName () {
console.log('fullName被调用');
return this.firstName + this.lastName;
},
},
})
</script>
</body>
</html>
通过我们调用方法,拿到方法的返回值来实现该功能。
1.3、姓名案例-计算属性实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>姓名案例-计算属性实现</title>
<script src="../js/vue.js" type="text/javascript"></script>
</head>
<body>
<!--
计算属性:
1.定义:要用的属性不存在,要通过已有属性计算得来。
2.原理:底层借助了objcet.defineproperty方法提供的getter和setter.
3.get函数什么时候执行?
(1).初次读取时会执行一次。
(2).当依赖的数据发生改变时会被再次调用。
4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
5.备注:
1.计算属性最终会出现在vm上,直接读取使用即可。
2.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生
-->
<div id="root">
姓:<input type="text" v-model="firstName" id=""><br>
名:<input type="text" v-model="lastName" id=""><br>
姓名:<span>{{fullName}}</span><br>
</div>
<script type="text/javascript">
const vm = new Vue({
el: '#root',
data () {
return {
firstName: '张',
lastName: '三'
}
},
computed: {
fullName: {
// get的调用时机:
// 1. 初次读取fullName时。2. 他所依赖的属性发生变化的时候会调用。
// computed相较于methods,它有缓存,只有上述条件满足的时候才会被调用。
get () {
console.log('get被调用');
return this.firstName + '-' + this.lastName;
},
// set的调用时机:
// 当fullName被修改的时候会被调用
set (value) {
console.log('set');
var arr = value.split("-");
this.firstName = arr[0];
this.lastName = arr[1];
}
// 在这里我们需要理解一下,我们的get会根据所依赖的属性来计算出fullName
// 而我们的set之后改变我们的fullName,不会影响所依赖的属性
},
},
})
</script>
</body>
</html>
计算属性需要在Vue配置对象中声明
computed对象
,而且非简写形式下的计算属性也是一个对象。
定义:要用的属性不存在,要通过已有属性计算得来。
原理:底层借助了objcet.defineproperty方法提供的getter和setter.
get函数什么时候执行?
- 初次读取时会执行一次。
- 当依赖的数据发生改变时会被再次调用。
优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
备注:
- 计算属性最终会出现在vm上,直接读取使用即可。
- 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生
计算属性的调用很简单:就是在双大括号中写出计算属性的名称(理解:计算属性也是属性嘛!)。
这个案例中没有调用set方法
。
1.4、姓名案例-计算属性的简写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>姓名案例-计算属性的简写</title>
<script src="../js/vue.js" type="text/javascript"></script>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName" id=""><br>
名:<input type="text" v-model="lastName" id=""><br>
姓名:<span>{{fullName}}</span><br>
</div>
<script type="text/javascript">
const vm = new Vue({
el: '#root',
data () {
return {
firstName: '张',
lastName: '三'
}
},
computed: {
// 简写的前提:只有读取没有修改(即:只有get没set)
fullName () {
console.log('get被调用');
return this.firstName + '-' + this.lastName;
}
},
})
</script>
</body>
</html>
计算属性的简写形式只适用于没有**set()**调用的情况下。简写形式是一个方法,返回一个值,这个值就是计算出来的属性。这和非简写形式下的
get()
很像,只不过方法名是计算属性的名称。
2、监视(侦听)属性
监视(侦听)就是可用用来监视某些数据的变化。进而可以做出相应的相应。
这里同样的用一个案例来演示监视属性
的好处。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GjpWTzSi-1679923029855)(Vue学习/image-20230312153907198.png)]
2.1、天气案例_计算属性实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气案例</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h1>今天天气{{info}}</h1>
<button @click="changeWeather">切换天气</button>
<button @click="isHot = !isHot">切换天气</button>
</div>
<script text="text/script">
Vue.config.productionTip = false;
new Vue({
el: '#root',
data () {
return {
isHot: true
}
},
methods: {
changeWeather () {
// 当我们要做的功能很单一的时候,我们可以直接将此表达式写到@click里边。
this.isHot = !this.isHot;
}
},
computed: {
info () {
return this.isHot ? '炎热' : '凉爽';
}
}
})
</script>
</body>
</html>
使用计算属性可以很简单的实现这个功能,但还有点不足。
2.2、天气案例_监视属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气案例_监视属性</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--
当监视属性变化的时候,回调函数handler会被调用,进行相关操作
监视的属性必须存在,才能进行监视
监视的两种写法:
(1).new Vue时传入watch配置
(2).通过vm.$watch监视
-->
<div id="root">
<h1>今天天气{{info}}</h1>
<button @click="changeWeather">切换天气</button>
</div>
<script text="text/script">
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data () {
return {
isHot: true
}
},
methods: {
changeWeather () {
this.isHot = !this.isHot;
}
},
computed: {
info () {
return this.isHot ? '炎热' : '凉爽';
}
},
// watch: {
// // 普通属性可以监视,计算属性也可以被监视
// isHot: {
// immediate: true, //初始化时让handler执行一下(默认是只有isHot改变的时候才会被调用)
// // handler调用的时机:当isHot发生改变时
// handler (newValue, oldValue) {
// console.log('isHot被修改了', newValue, oldValue);
// }
// }
// }
})
// 除了上述使用watch的方式,还有另外一种方式
vm.$watch('isHot', {
immediate: true, //初始化时让handler执行一下(默认是只有isHot改变的时候才会被调用)
// handler调用的时机:当isHot发生改变时
handler (newValue, oldValue) {
console.log('isHot被修改了', newValue, oldValue);
}
})
</script>
</body>
</html>
使用监视属性的两种方式:
在配置对象中声明
watch
对象。在创建完Vue实例对象之后,使用
$watch
来挂载。例: vm.$watch('被监视属性的名称', { immediate: true, handler (newValue, oldValue) { // 要进行的操作 } })
2.3、深度监视
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气案例_深度监视</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--
深度监视:
(1).vue中的watch默认不监测对象内部值的改变(一层)。
(2).配置deep:true可以监测对象内部值改变(多层)。
备注:
(1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
(2).使用watch时根据数据的具体结构,决定是否采用深度监视。
-->
<div id="root">
<h1>今天天气{{info}}</h1>
<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>
</div>
<script text="text/script">
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data () {
return {
isHot: true,
numbers: {
a: 1,
b: 1
}
}
},
methods: {
changeWeather () {
this.isHot = !this.isHot;
}
},
computed: {
info () {
return this.isHot ? '炎热' : '凉爽';
}
},
watch: {
isHot: {
handler (newValue, oldValue) {
console.log('isHot被修改了', newValue, oldValue);
}
},
// 监视多级结构中某个属性的变化
// 当我们需要监视对象中的某一个属性的时候,我们需要使用 '对象.属性' 的方式来使用。
// 因为我们不使用引号是一种简写方式,但这种情况不能使用简写
/*'numbers.a': {
handler () {
console.log("a被改变");
}
},*/
// 当我们想要监视numbers中的任意一个属性变化的时候,我们就进行相关操作
// 这里我们就需要用到 deep深度监视
numbers: {
deep: true,
handler () {
console.log('numbers被改变');
}
}
}
})
</script>
</body>
</html>
使用监听属性的注意点:
当监听的属性在第一级的时候,直接就可以监听到,不用开启深度监视。
当监听的属性是对象中的属性的时候,这里涉及到两种情况:
监听对象中的某个属性。这种情况下,我们不能使用
监视属性的简写形式
,而且不能直接将 number.a 写成 a。但这种情况下是不用开启深度监视的。'numbers.a': { handler () { console.log("a被改变"); } },
监听的是整个对象中的所有属性。这种情况下监听属性,监听不到数据的变化,必须要开启深度监视。
2.4、天气案例_监视属性简写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>天气案例_监视属性简写</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h1>今天天气{{info}}</h1>
<button @click="changeWeather">切换天气</button>
<hr>
</div>
<script text="text/script">
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data () {
return {
isHot: true,
}
},
methods: {
changeWeather () {
this.isHot = !this.isHot;
}
},
computed: {
info () {
return this.isHot ? '炎热' : '凉爽';
}
},
watch: {
// 正常写法
// isHot: {
// // immediate: true, //初始化时让handler执行一下(默认是只有isHot改变的时候才会被调用)
// // handler调用的时机:当isHot发生改变时
// handler (newValue, oldValue) {
// console.log('isHot被修改了', newValue, oldValue);
// }
// },
// 简写前提:不需要深度监视,只会使用handler的时候,才能简写
isHot (newValue, oldValue) {
console.log("isHot被修改了", newValue, oldValue);
}
}
})
</script>
</body>
</html>
深度监视的简写形式和它对象形式中写
handler()
很像,但就是方法名不再是handler而是被监听的属性名。
2.5、 补充:姓名案例-watch实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>姓名案例-watch实现</title>
<script src="../js/vue.js" type="text/javascript"></script>
</head>
<body>
<!--
computed和watch之间的区别:
1.computed能完成的功能,watch都可以完成。
2.watch能完成的功能,computed不一定能完成,例如: watch可以进行异步操作。
两个重要的小原则:
1.所被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或组件实例对象。
2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等),最好写成箭头函数,这样this的指向才是vm或组件实例对象。
-->
<div id="root">
姓:<input type="text" v-model="firstName" id=""><br>
名:<input type="text" v-model="lastName" id=""><br>
姓名:<span>{{fullName}}</span><br>
</div>
<script type="text/javascript">
const vm = new Vue({
el: '#root',
data () {
return {
firstName: '张',
lastName: '三',
fullName: '张-三'
}
},
watch: {
firstName (val) {
this.fullName = val + "-" + this.lastName;
},
lastName (val) {
this.fullName = this.firstName + "-" + val;
}
}
})
// computed和watch的对比
// computed不支持异步任务(因为computed依靠的是返回值),但watch可以
</script>
</body>
</html>
监听属性和计算属性实现 姓名案例 ,两者相比较,计算属性更加的简便。但这并不是说这两种形式一定那种好,只能说它们两个的使用是视情况而定的。
computed和watch的对比:
computed不支持异步任务(因为computed依靠的是返回值),但watch可以。
3、条件渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>条件渲染</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<!-- v-if和v-show的区别:
1. v-if为false的时候,元素会消失
2. v-show为false的时候,元素只是隐藏,它使用了display=none
两者的选用:
元素使用频率高就用v-show
元素使用频率低就用v-if
-->
<!-- 使用 v-show 做条件渲染 -->
<h2 v-show="a">欢迎{{name}}</h2>
<hr>
<!-- 使用 v-if 做条件渲染 -->
<h2 v-if="a">欢迎{{name}}</h2>
<hr>
<h2>当前的值是{{n}}</h2>
<button @click="n++">点我n+1</button>
<div v-show="n===1">Angular</div>
<div v-show="n===2">React</div>
<div v-show="n===3">Vue</div>
<!-- 只要其中一个条件成立,其余的判断就不会去执行。使用这些的时候,不允许打断 -->
<div v-if="n===1">Angular_1</div>
<div v-else-if="n===2">React_1</div>
<div v-esle-if="n===3">Vue_1</div>
<!-- 当上述条件都不成立的时候,就会执行v-else。v-else不需要写条件 -->
<div v-else>测试</div>
</div>
<script type="text/javascript">
new Vue({
el: '#root',
data () {
return {
name: '张三',
a: true,
n: 0
}
},
methods: {
},
})
</script>
</body>
</html>
和很多语言中都一样,通过条件的来判断数据是否显示等。
v-if
:通过条件的返回值来判断是否显示。
v-show
:和v-if
的功能一样。两种的区别:
- v-if为false的时候,元素会消失
- v-show为false的时候,元素只是隐藏,它使用了display=none
两者的选用:
- 元素使用频率高就用 v-show
- 元素使用频率低就用 v-if
v-else-if
和v-else
:使用和其他语言中一样。但需要注意的是:他们之间不允许打断。v-else
不用写条件。