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被触发时,它会通知观察者,进而重新渲染组件。

1.png

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; 
}

运行该程序后,你将会看到以下输出:

2.png

当你点击“Click Here”按钮时,计数器会递增。你会看到一个弹出的输出或一个alert消息显示counter属性的更改值。

3.png

示例解释

在上面的示例中,我们定义了一个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 globalVue.setVue.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方法也被删除了。

标签: vue, vuejs, vue框架, vue教程, vue学习, vue入门, vue入门教程, vue进阶, vue开发, vue框架使用, vue框架教程, vue框架编程, vue框架学习, vue框架学习教程