서문
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*에 추가 모델 레이어 데이터가 뷰에 표시될 때 복잡한 데이터 처리 로직이 있는 경우가 많습니다. 이 경우 계산된 속성을 사용하는 것이 더 합리적입니다.
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.width 또는 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에서 속성 관찰 모듈을 추출하고 캡슐화합니다.
ob.js GitHub 주소: https://github.com/cnlon/ob.js
설치
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