>  기사  >  웹 프론트엔드  >  Vue 계산 속성 및 리스너 케이스 코드 분석

Vue 계산 속성 및 리스너 케이스 코드 분석

php中世界最好的语言
php中世界最好的语言원래의
2018-05-22 11:39:171590검색

이번에는 vue 계산 속성 및 리스너 사례 코드 분석을 가져 왔습니다. vue 계산 속성 및 리스너 구현 시 주의 사항 은 무엇입니까?

기본 예

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

결과:

원본 메시지: "Hello"
계산된 역방향 메시지: "olleH"

여기서 계산된 속성 reversedMessage를 선언합니다. 우리가 제공하는 기능은 vm.reversedMessage 속성의 getter 기능으로 사용됩니다.

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

브라우저 콘솔을 열고 예제에서 VM을 직접 수정할 수 있습니다. vm.reversedMessage 값은 항상 vm.message 값에 따라 달라집니다. vm.reversedMessage 的值始终取决于 vm.message 的值。

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

计算属性缓存 vs 方法

你可能已经注意到我们可以通过在表达式中调用方法来达到同样的效果:

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

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

这也同样意味着下面的计算属性将不再更新,因为 Date.now() 不是响应式依赖:

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

相比之下,每当触发重新渲染时,调用方法将总会再次执行函数。

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

计算属性 vs 侦听属性

Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch——特别是如果你之前使用过 AngularJS。然而,通常更好的做法是使用计算属性而不是命令式的 watch 回调。细想一下这个例子:

<p id="demo">{{ fullName }}</p>
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'

일반 속성처럼 계산된 속성을 템플릿에 바인딩할 수 있습니다. Vue는 vm.reversedMessage가 vm.message에 의존한다는 것을 알고 있으므로 vm.message가 변경되면 vm.reversedMessage에 의존하는 모든 바인딩도 업데이트됩니다. 그리고 가장 좋은 부분은 선언적 방식으로 이 종속성을 생성했다는 것입니다. 계산된 속성 getter 함수에는 부작용이 없으므로 테스트하고 이해하기가 더 쉽습니다. 표현식

:

<p id="watch-example">
 <p>
  Ask a yes/no question:
  <input v-model="question">
 </p>
 <p>{{ answer }}</p>
</p>
<!-- 因为 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>
에서 메소드를 호출하여 동일한 효과를 얻을 수 있습니다. 계산된 속성 대신 메서드. 최종 결과는 실제로 두 가지 방법 모두 동일합니다. 그러나 차이점은 계산된 속성이 종속성에 따라 캐시된다는 것입니다. 계산된 속성은 관련 종속성이 변경될 때만 재평가됩니다. 즉, 메시지가 변경되지 않는 한 reversedMessage 계산 속성에 여러 번 액세스하면 함수를 다시 실행할 필요 없이 이전 계산 결과가 즉시 반환됩니다.

이는 Date.now()가 반응적 종속성이 아니기 때문에 아래 계산된 속성이 더 이상 업데이트되지 않는다는 의미이기도 합니다.

rrreee

반면, 다시 렌더링이 트리거될 때마다 호출 메서드는 항상 함수를 다시 실행합니다. .

캐싱이 왜 필요한가요? 거대한 배열을 순회하고 많은 계산을 수행해야 하는 계산 비용이 많이 드는 속성 A가 있다고 가정해 보겠습니다. 그러면 A에 의존하는 다른 계산된 속성이 있을 수 있습니다. 캐싱이 없으면 필연적으로 A의 getter를 여러 번 실행하게 됩니다! 캐싱을 원하지 않으면 대신 메소드를 사용하십시오.

계산된 속성과 청취 속성

Vue는 Vue 인스턴스의 데이터 변경 사항을 관찰하고 응답하는 보다 일반적인 방법인 청취 속성을 제공합니다. 다른 데이터 변경에 따라 변경해야 하는 일부 데이터가 있는 경우 시계를 남용하기 쉽습니다. 특히
AngularJS
. 그러나 명령형 감시 콜백 대신 계산된 속성을 사용하는 것이 더 나은 경우가 많습니다. 다음 예를 고려해 보세요.

rrreee위 코드는 필수적이고 반복적입니다. 계산된 속성 버전과 비교해 보세요. rrreee

훨씬 낫지 않나요? 🎜🎜🎜계산된 속성을 위한 Setter🎜🎜🎜계산된 속성에는 기본적으로 getter만 있지만 필요한 경우 setter를 제공할 수도 있습니다. 🎜rrreee🎜이제 vm.fullName = 'John Doe' 를 실행할 때, setter가 호출되고 vm.firstName 및 vm.lastName이 그에 따라 업데이트됩니다. 🎜🎜🎜Listeners🎜🎜🎜대부분의 경우 계산된 속성이 더 적합하지만 때로는 사용자 정의 리스너가 필요할 수도 있습니다. 이것이 Vue가 watch 옵션을 통해 데이터 변경에 응답하는 보다 일반적인 방법을 제공하는 이유입니다. 이 접근 방식은 데이터가 변경될 때 비동기식 또는 비용이 많이 드는 작업을 수행해야 할 때 가장 유용합니다. 🎜🎜예: 🎜rrreee🎜결과:🎜🎜🎜예/아니요 질문:🎜🎜질문을 하기 전까지는 답변을 드릴 수 없습니다!🎜🎜🎜이 예에서 watch 옵션을 사용하면 비동기 작업을 수행할 수 있습니다. (API에 액세스) 작업 수행 빈도를 제한하고 최종 결과를 얻을 때까지 중간 🎜상태🎜를 설정합니다. 이는 계산된 속성이 수행할 수 없는 작업입니다. 🎜

watch 옵션 외에도 명령형 vm.$watch API를 사용할 수도 있습니다.

이 기사의 사례를 읽은 후 방법을 마스터했다고 생각합니다. 더 흥미로운 정보를 보려면 PHP 중국어 웹사이트의 다른 관련 기사를 주목하세요!

추천 자료:

vuex와 구성 요소를 함께 사용하는 단계에 대한 자세한 설명

Vue에서 vux-ui 사용자 정의 양식 확인을 사용할 때 주의 사항은 무엇입니까

위 내용은 Vue 계산 속성 및 리스너 케이스 코드 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.