응답 시스템은 Vue의 중요한 기능입니다. 속성을 수정하면 뷰가 업데이트되어 상태 관리가 매우 간단하고 직관적이게 됩니다.
Vue 인스턴스를 생성할 때 Vue는 데이터 속성을 탐색하고 ES5의 Object.defineProperty를 통해 이를 getter/setter로 변환합니다. Vue는 내부적으로 종속성을 추적하고 변경 사항을 알릴 수 있습니다.
const vm = new Vue({ data: {foo: 1} // 'vm.foo' (在内部,同 'this.foo') 是响应的 })
속성 변경 관찰
Vue 인스턴스는 속성 변경을 관찰하기 위한 $watch 메서드를 제공합니다.
const vm = new Vue({ data: {foo: 1} }) vm.$watch('foo', function (newValue, oldValue) { console.log(newValue, oldValue) // 输出 2 1 console.log(this.foo) // 输出 2 }) vm.foo = 2
속성이 변경되면 응답 함수가 호출되며, 내부적으로는 Vue 인스턴스 vm에 자동으로 바인딩됩니다.
응답이 비동기적이라는 점에 유의해야 합니다. 다음과 같습니다:
const vm = new Vue({ data: {foo: 1} }) vm.$watch('foo', function (newValue, oldValue) { console.log('inner:', newValue) // 后输出 "inner" 2 }) vm.foo = 2 console.log('outer:', vm.foo) // 先输出 "outer" 2
데이터와 뷰의 바인딩은 $watch Vue를 통해 이루어집니다. 데이터 변경 사항이 관찰되면 Vue는 동일한 이벤트 루프 내에서 DOM을 비동기식으로 업데이트합니다. 다음 이벤트 루프에서는 Vue가 큐를 새로 고치고 필요한 업데이트만 수행합니다. 다음과 같습니다:
const vm = new Vue({ data: {foo: 1} }) vm.$watch('foo', function (newValue, oldValue) { console.log('inner:', newValue) // 后只输出一次 "inner" 5 }) vm.foo = 2 vm.foo = 3 vm.foo = 4 console.log('outer:', vm.foo) // 先输出 "outer" 4 vm.foo = 5
계산된 속성
MV*은 모델 레이어 데이터를 View에 표시할 때 복잡한 데이터 처리 논리를 갖는 경우가 많습니다. 이 경우 계산된 속성을 사용하는 것이 더 현명합니다.
const vm = new Vue({ data: { width: 0, height: 0, }, computed: { area () { let output = '' if (this.width > 0 && this.height > 0) { const area = this.width * this.height output = area.toFixed(2) + 'm²' } return output } } }) vm.width = 2.34 vm.height = 5.67 console.log(vm.area) // 输出 "13.27m²"
계산 속성 내부에서는 자동으로 vm에 바인딩되므로 계산 속성을 선언할 때 화살표 함수를 사용하지 않아야 합니다.
위의 예에서 vm.width 및 vm.height는 반응형입니다. vm.area가 this.width 및 this.height를 처음 읽으면 Vue는 이를 vm.area의 종속성으로 수집합니다. 너비 또는 vm.height가 변경되면 vm.area가 다시 평가됩니다.
계산된 속성은 종속성 캐시를 기반으로 합니다. vm.width 및 vm.height가 변경되지 않는 경우 vm.area를 여러 번 읽으면 다시 평가할 필요 없이 즉시 이전 계산 결과가 반환됩니다.
마찬가지로 vm.width 및 vm.height는 반응형이므로 vm.area의 변수에 종속 속성을 할당하고 변수를 읽어 속성을 읽는 횟수를 줄일 수 있습니다. 동시에 Vue는 문제를 해결합니다. 조건부 분기의 종속성을 수집할 수 없는 경우가 있습니다.
새로운 구현은 다음과 같습니다.
const vm = new Vue({ data: { width: 0, height: 0, }, computed: { area () { let output = '' const {width, height} = this if (width > 0 && height > 0) { const area = width * height output = area.toFixed(2) + 'm²' } return output } } }) vm.width = 2.34 vm.height = 5.67 console.log(vm.area) // 输出 "13.27m²"
ob.js를 통해 Vue의 속성 관찰 모듈을 단독으로 사용합니다.
학습 및 사용을 용이하게 하기 위해 ob.js는 Vue 그리고 그것을 캡슐화했습니다.
설치
npm install --save ob.js
속성 변경 관찰
const target = {a: 1} ob(target, 'a', function (newValue, oldValue) { console.log(newValue, oldValue) // 3 1 }) target.a = 3
계산된 속성 추가
const target = {a: 1} ob.compute(target, 'b', function () { return this.a * 2 }) target.a = 10 console.log(target.b) // 20
Vue를 선언하는 것처럼 매개변수 집합을 전달합니다. 인스턴스
const options = { data: { PI: Math.PI, radius: 1, }, computed: { 'area': function () { return this.PI * this.square(this.radius) }, }, watchers: { 'area': function (newValue, oldValue) { console.log(newValue) // 28.274333882308138 }, }, methods: { square (num) { return num * num }, }, } const target = ob.react(options) target.radius = 3