Vue计算属性computed的使用;methods VS 计算属性;侦听器watch;侦听器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.创建app
    const app = Vue.createApp({
      
      
      // data: option api
      data() {
      
      
        return {
      
      
          // 1.姓名
          firstName: "kobe",
          lastName: "bryant",

          // 2.分数: 及格/不及格
          score: 80,

          // 3.一串文本: 对文本中的单词进行反转显示
          message: "my name is hhh"
        }
      },
    })

    // 2.挂载app
    app.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.创建app
    const app = Vue.createApp({
      
      
      // data: option api
      data() {
      
      
        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.挂载app
    app.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.创建app
    const app = Vue.createApp({
      
      
      // data: option api
      data() {
      
      
        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.挂载app
    app.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.创建app
    const app = Vue.createApp({
      
      
      // data: option api
      data() {
      
      
        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.挂载app
    app.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.创建app
    const app = Vue.createApp({
      
      
      // data: option api
      data() {
      
      
        return {
      
      
          message: "Hello Vue",
          info: {
      
       name: "hhh", age: 18 }
        }
      },
      methods: {
      
      
        changeMessage() {
      
      
          this.message = "你好啊, 李银河!"
          this.info = {
      
       name: "kobe" }
        }
      },
      watch: {
      
      
        // 1.默认有两个参数: newValue/oldValue
        message(newValue, oldValue) {
      
      
          console.log("message数据发生了变化:", newValue, oldValue)
        },
        info(newValue, oldValue) {
      
      
          // 2.如果是对象类型, 那么拿到的是代理对象 Proxy
          console.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.挂载app
    app.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.创建app
    const app = Vue.createApp({
      
      
      // data: option api
      data() {
      
      
        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.挂载app
    app.mount("#app")
  </script>
</body>







































































猜你喜欢

转载自blog.csdn.net/qq_54075517/article/details/132148610