13_Vue中的计算属性

需求

10-24-9

  • 两个输入框
  • 下方一个全名
  • 要求输入框内容发生变化的时候,全名也跟着变化
  • 用计算属性很快能写出来,我们先用插值语法和methods配置项完成

methods和插值语法

方法1

使用插值语法和methods配置项完成

思路

  1. 为input输入框绑定 按键监听事件@keyup OR @keydown
  2. 发生按键监听的时候,通过类名判断是那个input触发的(event.srcElement.className)
  3. 然后在通过event的target获取当前元素,然后通过.value获取input输入的内容
  4. 值填充到对应的差值区域当中

准备工作

  <!-- 创建一个容器 -->
    <div class="app">
        <!-- 差值语法和methods -->
        <div class="box">
            <div class="title">差值语法methods</div>
            请输入:<input class="full" type="text" @keyup="writeContent"><br>
            请输入:<input class="name" type="text" @keyup="writeContent">
            <div class="content">你好!{{full}}-{{name}}</div>
        </div>
    </div>
var vm = new Vue({
        el: '.app',
        data: {
            name: '',
            full: ''
        },
        methods: {
            writeContent(e) {
                // 判断当前类名
                if (e.srcElement.className === "full") {
                    // 修改差值 full
                    // e.target获取当前DOM元素, .value获取当前输入框的值
                    this.full = e.target.value
                } else {
                    // 修改差值 name
                    // e.target获取当前DOM元素, .value获取当前输入框的值
                    this.name = e.target.value
                }

            },
        },
    });

测试

10-24-10

有点小bug,但是问题不大,功能实现了

出现问题的原因是,重置的时候只是重置了 input当中的value值,并没有重置data当中的变量值

针对方法1的优化(v-model)

  • 其实我是通过@keyup这个事件,获取input当中value的值
  • 然后在通过事件内部,将value值不断地赋予给 data当中的属性
  • 也就是这个事件是一直在被调用的(输入情况下)
  • 我们之前是通过v-model从而引出双向绑定的概念,但是我这次居然没有使用它,真是大失误
  • 因为v-model默认情况下就是服务于 value属性的,此时不用,更待何时

代码实现

html

 <!-- 创建一个容器 -->
    <form class="app">
        <input type="reset">
        <!-- 差值语法 == v-model -->
        <div class="box" >
            <div class="title">差值语法methods</div>
            请输入:<input type="text" v-model="full"><br>
            请输入:<input type="text" v-model="name">
            <div class="content">你好!{{full}}-{{name}}</div>
        </div>
    </form>

js

<script>
    var vm = new Vue({
      el: '.app',
      data: {
        name: '',
        full:""
      },
      methods: {

      },
    });
</script>

测试

10-25-1

这个bug依旧存在,因为input当中的reset并不能给vue当中的data清除数据

我们需要重写这个事件,或者通过其他方法来解决

关于methods的实现

怎么个实现方法?

我们首先需要理清下思路

  1. 我们配置的vue实例对象当中,有许多的配置项,例如当前学习的data和methods
  2. data和methods当中的属性和函数最终都挂载到了vue的实例身上
  3. 当我们使用插值语法的时候,能直接书写属性名or函数名,是因为这些都挂载在vue上面
  4. 怎么挂载的,后面再说,既然,属性名和函数都在vue身上
  5. 那么属性能使用插值语法,函数自然也可以使用插值语法

准备工作

<!-- 创建一个容器 -->
    <form class="app">
        <input type="reset">
        <!-- 差值语法 == v-model -->
        <div class="box" >
            <div class="title">差值语法methods</div>
            请输入:<input type="text" v-model="full"><br>
            请输入:<input type="text" v-model="name">
            <!-- 使用插值语法,将函数插入到其中 -->
            <!-- 函数的返回值会作为结果显示在页面当中 -->
            <div class="content">{{fullName()}}</div>
        </div>
    </form>

注意:一定要写完整的函数形式,否则vue会将其作为data当中的属性处理

image-20221025224251828

js

<script>
    var vm = new Vue({
      el: '.app',
      data: {
        name: '',
        full:""
      },
      methods: {
        fullName(){
            return "你好!" + this.full + "-" + this.name
        }
      },
    });
</script>

当我们使用普通函数形式的时候,this的指向就是vue实例,这个没啥多解释的

效果

10-25-2

计算属性

概念

首先我们需要知道一个事情,或者说回顾一个观点

  • 在vue的插值语法当中,该插值语法是可以识别表达式和vue当中的属性的
  • 所以,关于一些复杂的表达式,我们不应该书写在插值语法表达式当中
  • 应该使用更先进的语法 === 计算属性
  • 我们来看个例子

image-20221025224918950

来看看这个反例

image-20221025224937516

这是一个插值语法的表达式,但是这个表达式写的很复杂,不易阅读,这是vue的开发理念所杜绝的东西

而计算属性,就是我们接下来需要解读的部分

什么是计算属性

  1. 在data当中,一个属性分为两个部分组成
    1. key:属性名
    2. value:属性值
  2. 当然,这个就不多比比,上述说的这个东西叫做属性
  3. 那么什么是 计算属性?
  4. 很简单,计算机算,就是将你data当中的属性,进行加工,形成一个全新的属性,那么这个就是 计算属性

image-20221025225256318

这个右侧的fullName就是计算属性= firstName + lastName

全新配置项computed

  • 配置方法和data类似,对象的形式
  • 内部属性(计算属性),应当配置为 String:Object的形式
    • 因为 计算属性,你的表达式可能会很复杂
    • get:有人读取fullName的值,get就会被调用,且返回值就是fullName的值
    • set:有人修改fullName的属性,会获取到修改的value值,并将这个值重新赋予给fullName
    • 这和双向绑定是一个道理
  • 先看下写法吧

计算属性与普通属性一样使用插值语法书写

<!-- 创建一个容器 -->
    <form class="app">
        <input type="reset">
        <!-- 差值语法 == v-model -->
        <div class="box" >
            <div class="title">差值语法methods</div>
            请输入:<input type="text" v-model="full"><br>
            请输入:<input type="text" v-model="name">
            <!-- 使用计算属性 -->
            <div class="content">{{fullName}}</div>
        </div>
    </form>

js

<script>
    var vm = new Vue({
      el: '.app',
      data: {
        name: '',
        full: "",
      },
      // 配置计算属性
      computed:{
        fullName:{
            // 有人读取fullName的值,get就会被调用,且返回值就是fullName的值
            get(){
                return "张三"
            },
            // 有人修改fullName的属性,会获取到修改的value值,并将这个值重新赋予给fullName
            set(){
                
            },
        }
      }
    });
</script>

我们来看下效果

关于get

计算属性/属性

  • 计算属性同样是挂载在vue实例上的
  • 直接看的话,关于full、name、fullName
  • 我们是不能直接看出谁是计算属性谁是普通属性的

image-20221025230949140

细节问题

image-20221025231148389

  • 思考一个问题,我们可以通过计算属性对 full和name这两个data当中的属性进行加工
  • 那么,我怎么在get当中获取到full和name呢?
  • 直接像这样写吗?
    • image-20221025231251630
    • image-20221025231305179
    • full是没有被定义的,为什么?因为别人在data当中
  • data与computed是平级的,fullName这个属性在computed内部,get这个函数又在fullName内部
  • 你怎么访问?直接写肯定不行

this的指向

  • 用this吗?this的指向是谁?vue吗?为什么
  • 因为别人早就提前在get函数当中为我们指定好了this的指向

image-20221025231540624

get什么时候调用

缓存

image-20221025231847999

  • 根据之前的说法,有人读取fullName的值,那么get就会被调用
  • 那么上述这个图,fullName被调用几次?
  • 一次
  • 执行到第一次模板当中的fullName后,调用了get
  • 随后做了一个缓存,剩下三个地方在读取fullName的时候,就不找get要了,找缓存要

问题

  • 既然是找缓存要,那么fullName发生变化的时候,这个缓存不就拉了吗
  • 别急,人家还做了一个事情,你可以理解为更新缓存

get调用时机==初次读取

就是上述讲的那个

get调用时机==所在依赖数据发生变化的时候

  • fullName依赖的数据是谁? == > full + name嘛
  • 以后full或者name的属性值发生了改变,fullName也会随之改变
  • 为的就是给你最新的值
  • 如果做缓存的时候,不做这件事(所依赖数据发生变化的时候调用)
    • 那么就G了

10-25-3

full和name的值发生改动,fullName也会发生改动 == 因为所依赖的数据发生变化

优势

对于这个问题而言,methods是无法做缓存的,而computed是可以做的

image-20221025233059446

关于set

  • fullName的值发生修改的时候调用
  • 调用的时候set会获取修改的结果(value)

注意:是fullName的值发生变化,不是full和name的值发生变化

我们来看个例子

image-20221026083728456

测试

10-26-1

  • 这里显示的不齐全,通过上述测试,fullName的set方法中
  • 可以接受到value值
  • 但是没有对fullName进行修改,因为我们这里只是做了个无聊的输出
  • 那么能不能让fullName = value呢
    • image-20221026084356779

10-26-2

(精华部分)为什么不能直接修改fullName?

  • 可以这样理解,我们在大部分情况下,使用计算属性的时候,常使用的是get
  • 对于计算属性而言,他是依赖于其他的属性,会在计算属性的get函数当中,对所依赖的属性进行计算,然后将计算结果返回到插值表达式中
  • get的调用时机(2种
    • 第一次加载的时候,做缓存,页面其他地方还有使用了当前计算属性的插值表达式,不需要进行第二次/n次的get加载(很妙的思想)
    • 当 计算属性 所依赖的属性 发生变化的时候,get被重新调用
  • 以上就是get的调用时机,那么set到底是干嘛的?
  • set 是 你 如果需要求改 fullName单一修改 full/name的时候,set才会派上用场
    • 会接受到你传输的value值,但是这个value值并不能直接赋给fullName,否则就会报错,如上图所示
    • 在get的调用时机当中,当 所依赖的属性发生变化 get函数加载
    • 那么在set当中,如果你需要修改fullName,那么你必须要把 它所依赖的属性 full 和name一起修改才行
  • 我有点感觉,通过get接通从 full + name 与 fullName这条线
  • 通过set,则接通了从 fullName 到 full + name这条线

那么 为什么 姓和名之间 需要用 -号 分割了知道了吗,因为set的关系,如果不加上 - ,根本无法知道,到底谁属于 full 谁 属于name,所以需要这样

set的使用

// 配置计算属性
      computed:{
        fullName:{
            // 有人读取fullName的值,get就会被调用,且返回值就是fullName的值
            get(){
                return this.full + "-" + this.name
            },
            // 有人修改fullName的属性,会获取到修改的value值
            set(value){
                // full与name的修改会影响到fullName,fullName要修改,那么必须修改full与name
                // 对value进行分割
                var arr = value.split("-");
                this.name = arr[1]
                this.full = arr[0]                
            },
        }
      }
  • 使用split对字符串中的-,进行分割
  • 分割完后,将结果赋值给name和full

测试

10-26-3

总结

  • 1、
    • fullName没有真正的值
    • 你每次使用都是vue给算出来的
    • 算了还不要紧,vue还会给你把结果缓存下来,发生变动的时候再更新缓存
  • 2、
    • get与set不能写为箭头函数,否则还是那个老生常谈的问题,this指向会发生改变
    • 被vue所管理的函数不要使用箭头函数
  • 3、
    • 计算属性 如果要被修改,必须要写set函数
    • set函数当中,必须要使计算过程中所依赖的属性(full与name)发生改变

总结

image-20221026091731758

计算属性简写方式

要求

确定了该 计算属性,是只读的,不能被修改的(不使用set)

写法

  1. 使用简写形式,fullName,就不需要写成对象形式了
  2. 写成function函数形式
  3. 这个function,就是对应着我们完整写法当中的get

image-20221026092741315

// 简写形式
fullName:function(){
    return this.full + "-" + this.name
}

这不就是一个函数的写法吗,那为什么还要这么麻烦呢

// 简写
fullName(){
	return this.full + "-" + this.name		
}

函数名,就是计算属性的名字,内容则是get函数当中的内容,同样,不能使用箭头函数来代表

posted @ 2022-10-28 16:26  澜璨  阅读(107)  评论(0编辑  收藏  举报