1、计算属性
1.1、初识计算属性
1、为了防止数据冗余,我们使用实例属性computed来解决,computed是缓存机制,这个缓存机制就是作为参数用来计算的变量没有改变,那么就不会重复计算。
2、什么意思?比如说下面的fullName由firstName和lastName计算,页面开始的时候会计算一次fullName的值并缓存下来,在页面刷新或者过程中firstName和lastName没有发生变化,那么fullName一直用的是缓存的值。但是一但firstName和lastName发生了改变,那么fullName就会重新计算一次,并缓存下来。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vue计算属性,方法和侦听器</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
{{ fullName }}
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
firstName: "Dell",
lastName: "Lee",
},
//计算属性:解决数据的冗余
computed: {
fullName: function() {
console.log("计算了一次fullName");
return this.firstName + " " + this.lastName ;
}
},
})
</script>
</body>
</html>
1.2、计算属性的setter和getter
1、由于我们的上面的例子中fullName是计算属性中的,所以是依赖firstName和lastName,我们不能直接给fullName赋值来改变他,必须通过改变firstName和lastName的值来改变它,所以出现了setter和getter。
2、计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>计算属性的setter和getter</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
{{ fullName }}
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
firstName: 'Dell',
lastName: 'Lell',
},
computed: {
fullName: {
get: function() {
return this.firstName + " " + this.lastName;
},
set:function(value) {
var arr = value.split(" "); //以空格为分隔符,将arr分隔为字符串数组
this.firstName = arr[0];
this.lastName = arr[1];
}
}
}
})
</script>
</body>
</html>
2、方法
1、上面我们通过计算属性的方式来实现,实际上通过方法也能够实现同样的效果。但是注意的是,在插值表达式中使用methods中的方法要记得带上括号。如下所示:
2、虽然使用方法能和计算属性达到相同的效果,但是不如计算属性性能好,因为使用了方法,即使firstName或者lastName没有发生变化,如下列中你改变age这个和fullName完全不相关的变量,fullName也会重新计算一次,这种就很烦躁。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vue计算属性,方法和侦听器</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app"> <!--插值表达式中使用methods的方法要记得带上括号-->
{{ fullName() }}
{{ age }}
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
firstName: "Dell",
lastName: "Lee",
age: 22,
},
methods: {
fullName: function() {
console.log("计算了一次fullName");
return this.firstName + " " + this.lastName ;
}
}
})
</script>
</body>
</html>
3、侦听器(watch)
1、除了我们上面使用的两种方法,还有第三种放法可以实现这样的效果,侦听器,当数据发生变化,我们使用一个函数来写变化导致的操作。
2、watch这种方式和computed相比,也存在缓存机制,但是缺点也很明显,很复杂,而且需要侦听所有会导致fullNname变化的参数。所以这三个方法我们还是推荐computed这种方法,简洁,性能高。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vue侦听器</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
{{ fullName }}
{{ age }}
</div>
<script>
var vm = new Vue({
el: "#app",
data: {
firstName: 'Dell',
lastName: 'Lell',
fullName: 'Dell Lell',
age: 22,
},
//侦听器
watch: {
//监听firstName的变化,当firstName变化重新计算fullName
firstName: function() {
console.log("firstName导致的计算") ;
this.fullName = this.firstName + " " + this.lastName ;
},
lastName: function() {
console.log("lastName导致的计算") ;
this.fullName = this.firstName + " " + this.lastName ;
},
}
})
</script>
</body>
</html>
3、虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch
选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。下面这个是官方的例子,很有用:(这个例子就是在一个输入框中输入内容,每次的输入都会导致question的改变,由于使用了watch来监听,每次的输入都会去执行getAnswer函数,而这个函数中就是先判断有没有“?”,没有就自动return,认为你还没有输入完,当你输入?后,就开始去访问API,然后返回获得的数据)
<!-- 因为 AJAX 库和通用工具的生态已经相当丰富,Vue 核心代码没有重复 -->
<!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 -->
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script>
var watchExampleVM = new Vue({
el: '#watch-example',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
// 如果 `question` 发生改变,这个函数就会运行
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.debouncedGetAnswer()
}
},
created: function () {
// `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
// 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
// AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
// `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
// 请参考:https://lodash.com/docs#debounce
this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
},
methods: {
getAnswer: function () {
if (this.question.indexOf('?') === -1) {
this.answer = 'Questions usually contain a question mark. ;-)'
return
}
this.answer = 'Thinking...'
var vm = this
axios.get('https://yesno.wtf/api')
.then(function (response) {
vm.answer = _.capitalize(response.data.answer)
})
.catch(function (error) {
vm.answer = 'Error! Could not reach the API. ' + error
})
}
}
})
</script>
4、在这个示例中,使用 watch
选项允许我们执行异步操作 (访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。