zoukankan      html  css  js  c++  java
  • vue2.x学习笔记(五)

    接着前面的内容:https://www.cnblogs.com/yanggb/p/12571062.html

    计算属性

    模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。如果在模板中放入太多太多的逻辑,会让模板过重且难以维护。

    <div id="example">
      {{ message.split('').reverse().join('') }}
    </div>

    例如在上面这段代码中,模板不再是简单的声明式逻辑,你在阅读的时候必须要经过相当一段时间才能意识到,这里是想要显示变量message的反转字符串。当你想要在模板中多次引用此处的反转字符串的时候,就会更加难以处理,因为你可能要在多处引用中重复编写相同的表达式。因此,对于任何复杂的逻辑,都建议使用计算属性。

    计算属性的基础例子

    <div id="example">
      <p>Original message: "{{ message }}"</p>
      <p>Computed reversed message: "{{ reversedMessage }}"</p>
    </div>
    var vm = new Vue({
      el: '#example',
      data: {
        message: 'Hello'
      },
      computed: {
        // 计算属性的 getter
        reversedMessage: function () {
          // `this` 指向 vm 实例
          return this.message.split('').reverse().join('')
        }
      }
    })

    结果:

    Original message: "Hello"
    Computed reversed message: "olleH"

    在上面的例子中,声明了一个计算属性reversedMessage。我们提供的函数将用作属性vm.reversedMessage的getter函数。

    console.log(vm.reversedMessage) // => 'olleH'
    vm.message = 'Goodbye'
    console.log(vm.reversedMessage) // => 'eybdooG'

    这时候如果通过浏览器的控制台自行修改例子中的vm的话,vm.reversedMessage的值将会始终取决于vm.message的值。

    我们可以像绑定普通的属性那样在模板中绑定计算属性。因为vue知道vm.reversedMessage是依赖于vm.message的,因此当vm.message的值发生改变的时候,所有依赖于vm.reversedMessage的绑定也会更新。而且最妙之处在于,我们已经以声明式的方式创建了这种依赖关系:计算属性的getter函数是没有副作用(side effect)的,因为它并不会改变被依赖的属性值。比如前面的vm.reversedMessage并不会改变vm.message的值(单向依赖),使得计算属性易于测试和理解。

    计算属性缓存vs方法

    如果通过在表达式中调用方法的话,也可以达到与计算属性相同的效果。

    <p>Reversed message: "{{ reversedMessage() }}"</p>
    // 在组件中
    methods: {
      reversedMessage: function () {
        return this.message.split('').reverse().join('')
      }
    }

    从上面这个例子可以看出,我们可以将同一个函数定义为一个方法而不是一个计算属性,而两种方式的最终结果确实是完全相同的。然而,这两种方式不同的地方在于,计算属性是基于它们的响应式依赖进行缓存的,计算属性是基于它们的响应式依赖进行缓存的,计算属性是基于它们的响应式依赖进行缓存的,只在相关响应式依赖发生改变的时候,计算属性才会重新求值。这也就意味着,只要message还没有发生改变,多次访问reversedMessage计算属性会立即返回之前的计算结果,而不必再次执行函数,这样的特性被称为【缓存性】。

    computed: {
      now: function () {
        return Date.now()
      }
    }

    那么,在上面这个例子中,因为Date.now()不是响应式更新,now这个计算属性将不再更新。而相比之下,每当触发重新渲染的时候,调用方法将总会再次执行函数。

    缓存的意义在于提升页面性能。假设有一个性能开销很大的计算属性A,它需要遍历一个巨大的数组并做大量的运算,而且这时候还有另一个计算属性B依赖于A,如果A没有缓存的话,我们就会不可避免地多次执行计算属性A的getter函数,哪怕返回的结果值并没有发生任何改变。而有了【缓存性】这一特性,则避免了不必要的多次执行计算属性A的getter函数,可能极大地提升页面性能。

    而如果不需要缓存的话,则可以使用方法来替代,因为可以说除【缓存性】这一特性之外,两者几乎没有任何差别了。

    计算属性的getter

    计算属性默认只有getter,不过在需要的时候,你也可以提供一个setter。

    // ...
    computed: {
      fullName: {
        // getter
        get: function () {
          return this.firstName + ' ' + this.lastName
        },
        // setter
        set: function (newValue) {
          var names = newValue.split(' ')
          this.firstName = names[0]
          this.lastName = names[names.length - 1]
        }
      }
    }
    // ...

    这个时候,如果再浏览器控制台中运行vm.fullName = 'xxx xxxx'的时候,setter函数就会被调用,vm.firstName和vm.lastName也会相应地被更新。

    侦听器(侦听属性)

    vue提供了一种更通用的方式来观察和响应vue实例上的数据变动。虽然计算属性在大多数的情况下更合适,但是有时候也需要一个自定义的侦听器(侦听属性)。当需要在数据变化的时候执行异步或开销较大的操作时,这个方式十分有用。

    <div id="watch-example">
      <p>
        Ask a yes/no question:
        <input v-model="question">
      </p>
      <p>{{ answer }}</p>
    </div>
    <!-- 因为 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('http://www.yanggb.com.cn/api')
            .then(function (response) {
              vm.answer = _.capitalize(response.data.answer)
            })
            .catch(function (error) {
              vm.answer = 'Error! Could not reach the API. ' + error
            })
        }
      }
    })
    </script>

    在这个示例中,使用watch选项允许我们执行异步操作 (访问一个API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。

    侦听属性vs计算属性

    当你有一些数据需要随着其它数据变动而变动时候,你很容易会滥用watch侦听属性,而通常更好的做法则是使用计算属性而不是命令式的watch回调。

    <div id="demo">{{ fullName }}</div>
    var vm = new Vue({
      el: '#demo',
      data: {
        firstName: 'Foo',
        lastName: 'Bar',
        fullName: 'Foo Bar'
      },
      watch: {
        firstName: function (val) {
          this.fullName = val + ' ' + this.lastName
        },
        lastName: function (val) {
          this.fullName = this.firstName + ' ' + val
        }
      }
    })

    在上面的这段代码中,侦听了firstName和lastName两个属性,这两个属性如果发生了改变,则会触发侦听属性的回调函数,将两个属性值拼接到fullName属性中。这种方式是命令式的,且两个侦听属性功能重复。

    var vm = new Vue({
      el: '#demo',
      data: {
        firstName: 'Foo',
        lastName: 'Bar'
      },
      computed: {
        fullName: function () {
          return this.firstName + ' ' + this.lastName
        }
      }
    })

    改成了声明式的计算属性之后,代码就显得简洁且清晰了很多。

    "我还是很喜欢你,像时光低眉莞尔,千言万语。"

  • 相关阅读:
    关于32位操作系统和64位操作系统对InstallShield打包的影响
    NEWS: Symantec宣布Wise Package Studio将终止
    InstallShield 2012新功能试用(2) 调用MsiGetProperty等MSI API发生变化
    Basic INFO 在命令行Build InstallShield安装包工程获得压缩安装包
    NEWS InstallShield 2012 Service Pack 1发布
    Basic INFO InstallShield Basic MSI工程中如何在SetupCompleteSuccess界面中启动Readme
    Basic INFO InstallShield的脚本编辑器中如何显示代码行号
    Basic INFO 关于在InstallShield制作的安装包界面中删除InstallShield文字的厂商回复
    Basic INFO InstallShield工程中如何让产品的快捷方式名称始终与产品名保持一致
    Basic INFO: 创建隐藏文件夹
  • 原文地址:https://www.cnblogs.com/yanggb/p/12571171.html
Copyright © 2011-2022 走看看