目录
- 1_computed计算属性使用
- 1.1_复杂data的处理方式
- 1.2_计算属性computed
- 1.3_计算属性 vs methods
- 1.4_计算属性的setter和getter(了解)
- 2_侦听器watch
- 2.1_认识
- 2.2_侦听器watch的配置选项
1_computed计算属性使用
1.1_复杂data的处理方式
在模板中可以直接通过插值语法显示一些data中的数据,比如下面的代码
<body><div id="app"><!-- 插值语法表达式直接进行拼接 --><!-- 1.拼接名字 --><h2>{{ firstName + " " + lastName }}</h2><h2>{{ firstName + " " + lastName }}</h2><h2>{{ firstName + " " + lastName }}</h2><!-- 2.显示分数等级 --><h2>{{ score >= 60 ? '及格': '不及格' }}</h2><!-- 3.反转单词显示文本 --><h2>{{ message.split(" ").reverse().join(" ") }}</h2></div><script src="../lib/vue.js"></script><script>// 1.创建appconst app = Vue.createApp({// data: option apidata() {return {// 1.姓名firstName: "kobe",lastName: "bryant",// 2.分数: 及格/不及格score: 80,// 3.一串文本: 对文本中的单词进行反转显示message: "my name is hhh"}},})// 2.挂载appapp.mount("#app")</script>
</body>
在某些情况,需要对数据进行一些转化后再显示,或者将多个数据结合起来进行显示;
- 比如需要对多个data数据进行运算、三元运算符来决定结果、数据进行某种转化后显示;
- 在模板中使用表达式,可以非常方便的实现,但是设计它们的初衷是用于简单的运算;
- 在模板中放入太多的逻辑会让模板过重和难以维护;
- 并且如果多个地方都使用到,那么会有大量重复的代码;
将逻辑抽离出去的方法?
- 一种方式就是将逻辑抽取到一个method中,放到methods的options中;但是,这种做法有一个直观的弊端,就是所有的data使用过程都会变成了一个方法的调用;
<body><div id="app"><!-- 插值语法表达式直接进行拼接 --><!-- 1.拼接名字 --><h2>{{ getFullname() }}</h2><h2>{{ getFullname() }}</h2><h2>{{ getFullname() }}</h2><!-- 2.显示分数等级 --><h2>{{ getScoreLevel() }}</h2><!-- 3.反转单词显示文本 --><h2>{{ reverseMessage() }}</h2></div><script src="../lib/vue.js"></script><script>// 1.创建appconst app = Vue.createApp({// data: option apidata() {return {// 1.姓名firstName: "kobe",lastName: "bryant",// 2.分数: 及格/不及格score: 80,// 3.一串文本: 对文本中的单词进行反转显示message: "my name is hhh"}},methods: {getFullname() {return this.firstName + " " + this.lastName},getScoreLevel() {return this.score >= 60 ? "及格": "不及格"},reverseMessage() {return this.message.split(" ").reverse().join(" ")}}})// 2.挂载appapp.mount("#app")</script>
</body>
- 另外一种方式就是使用计算属性computed;
1.2_计算属性computed
如何理解?
- 官方并没有给出直接的概念解释;
- 而是说:对于任何包含响应式数据的复杂逻辑,你都应该使用计算属性;
- 计算属性将被混入到组件实例中: 所有 getter 和 setter 的 this 上下文自动地绑定为组件实例;
计算属性的用法:
- 选项:computed
- 类型:{ [key: string]: Function | { get: Function, set: Function } }
按照1.1的代码,使用computed属性
<body><div id="app"><!-- 1.拼接名字 --><h2>{{ fullname }}</h2><h2>{{ fullname }}</h2><h2>{{ fullname }}</h2><!-- 2.显示分数等级 --><h2>{{ scoreLevel }}</h2><!-- 3.反转单词显示文本 --><h2>{{ reverseMessage }}</h2></div><script src="../lib/vue.js"></script><script>// 1.创建appconst app = Vue.createApp({// data: option apidata() {return {// 1.姓名firstName: "kobe",lastName: "bryant",// 2.分数: 及格/不及格score: 80,// 3.一串文本: 对文本中的单词进行反转显示message: "my name is hhh"}},computed: {// 1.计算属性默认对应的是一个函数fullname() {return this.firstName + " " + this.lastName},scoreLevel() {return this.score >= 60 ? "及格": "不及格"},reverseMessage() {return this.message.split(" ").reverse().join(" ")}}})// 2.挂载appapp.mount("#app")</script>
</body>
1.3_计算属性 vs methods
虽然计算属性和methods的实现代码看起来差别不大,但是计算属性有缓存的。
计算属性会基于它们的依赖关系进行缓存;
- 在数据不发生变化时,计算属性是不需要重新计算的;但是methods是调用一次,就计算一次,对比之下,比较消耗性能。
- 但是如果依赖的数据发生变化,在使用时,计算属性依然会重新进行计算;
所以,建议优先使用计算属性computed
1.4_计算属性的setter和getter(了解)
计算属性在大多数情况下,只需要一个getter方法即可,所以会将计算属性直接写成一个函数。
<body><div id="app"><h2>{{ fullname }}</h2><button @click="setFullname">设置fullname</button></div><script src="../lib/vue.js"></script><script>// 1.创建appconst app = Vue.createApp({// data: option apidata() {return {firstname: "coder",lastname: "hhh"}},computed: {// 语法糖的写法// fullname() {// return this.firstname + " " + this.lastname// },// 完整的写法:fullname: {get: function() {return this.firstname + " " + this.lastname},set: function(value) {const names = value.split(" ")this.firstname = names[0]this.lastname = names[1]}}},methods: {setFullname() {this.fullname = "kobe bryant"}}})// 2.挂载appapp.mount("#app")</script>
</body>
2_侦听器watch
2.1_认识
侦听器?
- 开发中在data返回的对象中定义了数据,这个数据通过插值语法等方式绑定到template中;
- 当数据变化时,template会自动进行更新来显示最新的数据;
- 但是在某些情况下,希望在代码逻辑中监听某个数据的变化,这时就需要侦听器watch来完成了;
侦听器的用法如下:
- 选项:watch
- 类型:{ [key: string]: string | Function | Object | Array}
案例:
- 比如现在希望用户在input中输入一个问题;
- 每当用户输入了最新的内容,就获取到最新的内容,并且使用该问题去服务器查询答案;
- 那么,就需要实时的去获取最新的数据变化;
<body><div id="app"><h2>{{message}}</h2><button @click="changeMessage">修改message</button></div><script src="../lib/vue.js"></script><script>// Proxy -> Reflect// 1.创建appconst app = Vue.createApp({// data: option apidata() {return {message: "Hello Vue",info: { name: "hhh", age: 18 }}},methods: {changeMessage() {this.message = "你好啊, 李银河!"this.info = { name: "kobe" }}},watch: {// 1.默认有两个参数: newValue/oldValuemessage(newValue, oldValue) {console.log("message数据发生了变化:", newValue, oldValue)},info(newValue, oldValue) {// 2.如果是对象类型, 那么拿到的是代理对象 Proxyconsole.log("info数据发生了变化:", newValue, oldValue)// Proxy(Object) {name: 'kobe'} // Proxy(Object) {name: 'hhh', age: 18}console.log(newValue.name, oldValue.name) //kobe hhh// 3.获取原生对象console.log({ ...newValue }) //{name: 'kobe'}console.log(Vue.toRaw(newValue)) //{name: 'kobe'}}}})// 2.挂载appapp.mount("#app")</script>
</body>
2.2_侦听器watch的配置选项
一个例子:
- 当点击按钮的时候会修改info.name的值;
- 这个时候使用watch来侦听info,可以侦听到吗?答案是不可以。
因为默认情况下,watch只是在侦听info的引用变化,对于内部属性的变化是不会做出响应的:
- 这个时候可以使用一个选项deep进行更深层的侦听;
- 注意watch里面侦听的属性对应的也可以是一个Object;
immediate属性,一开始的就会立即执行一次:
- 这个时候使用immediate选项;
- 这个时候无论后面数据是否有变化,侦听的函数都会执行一次;
<body><div id="app"><h2>{{ info.name }}</h2><button @click="changeInfo">修改info</button></div><script src="../lib/vue.js"></script><script>// 1.创建appconst app = Vue.createApp({// data: option apidata() {return {info: { name: "hhh", age: 18 }}},methods: {changeInfo() {// 1.创建一个新对象, 赋值给info// this.info = { name: "kobe" }// 2.直接修改原对象某一个属性this.info.name = "kobe"}},watch: {// 默认watch监听不会进行深度监听// info(newValue, oldValue) {// console.log("侦听到info改变:", newValue, oldValue)// }// 修改代码,进行深度监听info: {handler(newValue, oldValue) {console.log("侦听到info改变:", newValue, oldValue)console.log(newValue === oldValue)},// 监听器选项:// info进行深度监听deep: true,// 第一次渲染直接执行一次监听器immediate: true},"info.name": function(newValue, oldValue) {console.log("name发生改变:", newValue, oldValue)}}})// 2.挂载appapp.mount("#app")</script>
</body>