模板渲染,computed,methods,watch,生命周期

Vue.js核心概念
本文介绍Vue.js的关键特性,包括模板渲染、计算属性、侦听器及生命周期钩子等。通过实例展示如何使用Vue进行高效开发。

Vue是一套用于构建用户界面的渐进式框架。

模板渲染

# “Mustache”语法 {{}}的文本插值:
<span>Message: {{ msg }}</span>
绑定的数据对象上 msg 属性发生了改变,插值处的内容都会更新。

# v-once 能执行一次性地插值,当数据改变时,插值处的内容不会更新。
<span v-once>这个将不会改变: {{ msg }}</span>

#{{}}会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html 指令:
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
!动态渲染的 HTML 可能会导致 XSS 攻击。

 #v-bind/':':绑定HTML特性
<div v-bind:id="dynamicId"></div>
复制代码

计算属性computed

类型:{ [key: string]: Function | { get: Function, set: Function } }

<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('')
    }
  }
})
复制代码

计算属性缓存 vs 方法

类型:{ [key: string]: Function | { get: Function, set: Function } }

通过在表达式中调用方法来达到同样的效果:
<p>Reversed message: "{{ reversedMessage() }}"</p>
// 在组件中
methods: {
  reversedMessage: function () {
    return this.message.split('').reverse().join('')
  }
}

计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。这就意味
着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,
而不必再次执行函数。
相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。

我们为什么需要缓存?假设我们有一个性能开销比较大的的计算属性 A,它需要遍历一个巨大的数组并做大
量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 
getter!如果你不希望有缓存,请用方法来替代。
复制代码

计算属性 vs 侦听属性

类型:{ [key: string]: Function | { get: Function, set: Function } }

Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。当你有一些数据需要随着
其它数据变动而变动时,你很容易滥用 watch——特别是如果你之前使用过 AngularJS。然而,通常更好的
做法是使用计算属性而不是命令式的 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
    }
  }
})

上面代码是命令式且重复的。将它与计算属性的版本进行比较:

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


计算属性的 setter
计算属性默认只有 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 = 'John Doe' 时,setter 会被调用,vm.firstName和 vm.lastName 
也会相应地被更新。
复制代码

侦听器watch

当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
例如:
<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.getAnswer()
    }
  },
  methods: {
    // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
    // 在这个例子中,我们希望限制访问 yesno.wtf/api 的频率
    // AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
    // `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识,
    // 请参考:https://lodash.com/docs#debounce
    getAnswer: _.debounce(
      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
          })
      },
      // 这是我们为判定用户停止输入等待的毫秒数
      500
    )
  }
})
</script>

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

生命周期钩子

所有的生命周期钩子自动绑定 this 上下文到实例中,因此你可以访问数据,对属性和方法进行运算。这意味
着 你不能使用箭头函数来定义一个生命周期方法 (例如 created: () => this.fetchTodos())。这是
因为箭头函数绑定了父上下文,因此 this 与你期待的 Vue 实例不同,this.fetchTodos 的行为未定义。

# beforeCreate 类型:Function
在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。

# created  类型:Function
在实例创建完成后被立即调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方
法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。

# beforeMount 类型:Function
在挂载开始之前被调用:相关的 render 函数首次被调用。
该钩子在服务器端渲染期间不被调用。

# mounted  类型:Function
el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,
当 mounted 被调用时 vm.$el 也在文档内。
注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 
vm.$nextTick 替换掉 mounted:
mounted: function () {
  this.$nextTick(function () {
    // Code that will run only after the
    // entire view has been rendered
  })
}
该钩子在服务器端渲染期间不被调用。

# beforeUpdate  类型:Function
数据更新时调用,发生在虚拟 DOM 打补丁之前。这里适合在更新之前访问现有的 DOM,比如手动移除已添加
的事件监听器。
该钩子在服务器端渲染期间不被调用,因为只有初次渲染会在服务端进行。

# updated 类型:Function
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下
,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。

注意 updated 不会承诺所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以用
vm.$nextTick 替换掉 updated:

updated: function () {
  this.$nextTick(function () {
    // Code that will run only after the
    // entire view has been re-rendered
  })
}
该钩子在服务器端渲染期间不被调用。

# activated 类型:Function

keep-alive 组件激活时调用。
该钩子在服务器端渲染期间不被调用。

# deactivated 类型:Function

keep-alive 组件停用时调用。
该钩子在服务器端渲染期间不被调用。

# beforeDestroy 类型:Function
实例销毁之前调用。在这一步,实例仍然完全可用。
该钩子在服务器端渲染期间不被调用。

# destroyed 类型:Function
Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子
实例也会被销毁。

该钩子在服务器端渲染期间不被调用。

# errorCaptured (2.5.0+ 新增)类型:(err: Error, vm: Component, info: string) => ?boolean
当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生错误的组件实例以及一个包含
错误来源信息的字符串。此钩子可以返回 false 以阻止该错误继续向上传播。

你可以在此钩子中修改组件的状态。因此在模板或渲染函数中设置其它内容的短路条件非常重要,它可以防止当一
个错误被捕获时该组件进入一个无限的渲染循环。

错误传播规则
默认情况下,如果全局的 config.errorHandler 被定义,所有的错误仍会发送它,因此这些错误仍然会向
单一的分析服务的地方进行汇报。
如果一个组件的继承或父级从属链路中存在多个 errorCaptured 钩子,则它们将会被相同的错误逐个唤起。
如果此 errorCaptured 钩子自身抛出了一个错误,则这个新错误和原本被捕获的错误都会发送给全局的 
config.errorHandler。

一个 errorCaptured 钩子能够返回 false 以阻止错误继续向上传播。本质上是说“这个错误已经被搞定了
且应该被忽略”。它会阻止其它任何会被这个错误唤起的 errorCaptured 钩子和全局的config.errorHandler。
复制代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值