Vuejs教程-Vue.js 响应性系统
Vue.js的响应性系统是其最独特的功能之一。在Vue.js中,模型是普通的JavaScript对象。当我们修改模型时,视图会自动更新。这使得状态管理简单直观,但也需要了解其工作原理,以避免一些常见的问题。在这里,我们将了解如何使用响应性系统来解决这些问题。
工作原理
如果将一个普通的JavaScript对象作为数据选项传递给Vue.js实例,你会发现Vue.js会通过Object.defineProperty
将其所有属性转换为getter/setter。
这是一个不可修改且仅在ES5中支持的特性。由于这个特性,Vue不支持IE8及以下版本。
尽管用户看不到getter和setter属性,但在底层它们使得Vue.js能够执行依赖跟踪和当你需要改变或访问属性时进行变更通知。你可以在浏览器的控制台中看到getter/setter属性的变化。若要查看它们,你需要安装vue-devtools
,它提供更友好的检查界面。
每个组件实例都有一个相应的观察者实例。这个观察者用于在组件渲染时记录作为依赖项的属性。之后,当依赖项的setter被触发时,它会通知观察者,进而重新渲染组件。
Vue.js响应式接口
Vue.js提供了一种方式来将动态添加的属性添加到响应式系统中。假设我们已经创建了Vue.js实例,并且我们想要添加一个watch
属性。请看下面的示例:
示例:
Index.html文件:
<!DOCTYPE html>
<html>
<head>
<title>Vue.js Reactive Interface</title>
<link rel="stylesheet" href="index.css">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="reactivity_1">
<p style="font-size: 25px;">Counter: {{ counter }}</p>
<button @click="counter++" style="font-size: 25px;">Click Here</button>
</div>
<script src="index.js"></script>
</body>
</html>
Index.js文件:
var vm = new Vue({
el: '#reactivity_1',
data: {
counter: 1
}
});
vm.$watch('counter', function(nval, oval) {
alert('Counter is incremented: ' + oval + ' to ' + nval + '!');
});
setTimeout(function() {
vm.counter = 10;
}, 1000);
让我们使用简单的CSS文件使输出更加美观。
Index.css文件:
html, body {
margin: 5px;
padding: 0;
}
运行该程序后,你将会看到以下输出:
当你点击“Click Here”按钮时,计数器会递增。你会看到一个弹出的输出或一个alert消息显示counter属性的更改值。
示例解释
在上面的示例中,我们定义了一个counter属性,它在数据对象中设置为1。当你点击“Click Here”按钮时,计数器会递增。
在创建Vue.js实例后,我们要为它添加一个watch属性。使用以下代码添加它:
vm.$watch('counter', function(nval, oval) {
alert('Counter is incremented: ' + oval + ' to ' + nval + '!');
});
我们使用了$watch
属性在Vue实例之外添加watch。我们还添加了一个alert,用于显示counter属性的值变化。还添加了一个名为setTimeout
的定时器函数,将计数器的值设置为10。
setTimeout(function() {
vm.counter = 10;
}, 1000);
每当你点击按钮时,计数器会改变,触发watch方法中的alert。
动态添加属性
最好总是在Vue.js实例中预先声明需要响应式的属性,因为Vue.js无法检测属性的添加和删除。
如果你想在运行时添加属性,你必须使用Vue global
的Vue.set
和Vue.delete
方法。
Vue.set
用于设置对象的属性。它用于解决Vue.js无法检测属性添加的限制。
语法
Vue.set(target, key, value);
这里:
target
:可以是一个对象或数组。key
:可以是一个字符串或数字。value
:可以是任意类型。
让我们通过一个简单的示例了解Vue.set
的概念。
示例:
Index.html文件:
<!DOCTYPE html>
<html>
<head>
<title>Vue.js Reactive Interface</title>
<link rel="stylesheet" href="index.css">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="reactivity_1">
<p style="font-size: 25px;">Counter value: {{ products.id }}</p>
<button @click="products.id++" style="font-size: 25px;">Click Here</button>
</div>
<script src="index.js"></script>
</body>
</html>
Index.js文件:
var myproduct = { "id": 1, "name": "shirt", "price": "1000.00" };
var vm = new Vue({
el: '#reactivity_1',
data: {
counter: 1,
products: myproduct
}
});
Vue.set(myproduct, 'qty', 1);
console.log(vm);
vm.$watch('counter', function(nval, oval) {
alert('Counter is incremented: ' + oval + ' to ' + nval + '!');
});
在上面的示例中,我们首先在开头创建了一个名为myproduct
的变量:
var myproduct = { "id": 1, "name": "shirt", "price": "1000.00" };
然后将其作为数据对象给了Vue.js实例:
var vm = new Vue({
el: '#reactivity_1',
data: {
counter: 1,
products: myproduct
}
});
假设在创建Vue.js实例后,需要向myproduct
数组添加一个属性。你可以使用以下代码:
Vue.set(myproduct, 'qty', 1);
如果你在控制台上运行此示例,你将看到在products列表中添加了数量(qty)。getter/setter方法,它们基本上添加了响应性,对于id、name和price是可用的,而对于qty则不可用。
因此,你可以看到响应性不能仅通过添加Vue对象来实现。在Vue.js中,你必须在开始时创建其所有属性。如果你希望以后进行添加,我们可以使用Vue.set。在下面的示例中,我们以稍后添加所有属性的方式演示。
示例:
Index.html文件:
<!DOCTYPE html>
<html>
<head>
<title>Vue.js Reactive Interface</title>
<link rel="stylesheet" href="index.css">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="reactivity_1">
<p style="font-size: 25px;">Counter value: {{ products.id }}</p>
<button @click="products.id++" style="font-size: 25px;">Click Here</button>
</div>
<script src="index.js"></script>
</body>
</html>
Index.js文件:
var myproduct = { "id": 1, "name": "shirt", "price": "1000.00" };
var vm = new Vue({
el: '#reactivity_1',
data: {
counter: 1,
products: myproduct
}
});
Vue.set(myproduct, 'qty', 1);
console.log(vm);
vm.$watch('counter', function(nval, oval) {
alert('Counter is incremented: ' + oval + ' to ' + nval + '!');
});
在上面的示例中,我们使用了Vue.set
函数来在创建Vue实例后向数组添加qty
属性:
Vue.set(myproduct, 'qty', 1);
运行这个示例时,你将会看到在products列表中,已添加了一个qty。getter/setter方法也是可用的。
Vue.delete
Vue.delete
函数用于动态删除属性。这也是为了解决Vue.js无法检测属性删除的限制。
语法:
Vue.delete(target, key);
这里:
target
:用于指定一个对象或数组。key
:用于指定一个字符串或数字。
让我们看一个示例来演示如何使用Vue.delete
函数在Vue.js中动态删除属性。
示例:
Index.html文件:
<!DOCTYPE html>
<html>
<head>
<title>Vue.js Reactive Interface</title>
<link rel="stylesheet" href="index.css">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="reactivity_1">
<p style="font-size: 25px;">Counter value: {{ products.id }}</p>
<button @click="products.id++" style="font-size: 25px;">Click Here</button>
</div>
<script src="index.js"></script>
</body>
</html>
Index.js文件:
var myproduct = { "id": 1, "name": "shirt", "price": "1000.00" };
var vm = new Vue({
el: '#reactivity_1',
data: {
counter: 1,
products: myproduct
}
});
Vue.delete(myproduct, 'price');
console.log(vm);
vm.$watch('counter', function(nval, oval) {
alert('Counter is incremented: ' + oval + ' to ' + nval + '!');
});
在上面的示例中,我们使用了Vue.delete
函数来删除数组中的price
属性:
Vue.delete(myproduct, 'price');
当你在控制台上运行这个示例时,你会发现只有id和name在控制台上可见,因为price已被删除。你还会注意到getter/setter方法也被删除了。