data为何以函数形式返回

在使用Vue构建组件化应用时, 每个组件的data属性都是以函数形式返回的, 这主要是在组件化实现的时候, 每个实例可以维护一份被返回对象的独立的拷贝, 而不是共享同一个对象的引用

Vue简单实例

在一个Vue简单实例中, 也就是不使用组件化实现的时候, data可以是一个对象, 因为本身也只有一个实例, 就不存在多个实例共享的问题

<!DOCTYPE html>
<html>
<head>
  <title>Vue</title>
</head>

<body>
  <div id="app">
    <div>{{msg}}</div>
  </div>
</body>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
<script type="text/javascript">
  let vm = new Vue({
    el: "#app",
    data: {
      msg: "Vue Instance"
    }
  })
</script>
</html>
复制代码

组件化实例

如果是使用Vue的组件化实例, 那么data属性就必须以函数的形式返回, 如果不使用函数的形式返回, 可能会出现一些意料之外的情况, 比如下面的例子中, 按钮组件是复用的, 在点击第一个按钮时本身应该只有一个按钮+1, 但是所有的按钮都跟随+1. 请注意, 在此处仍然是使用函数的形式返回, 这是因为如果在组件化实现中如果不使用函数的形式返回Vue会直接报错, 但是实现的效果是相同的, 虽然是以函数的形式返回, 但是返回的对象中count属性都是指向了对于counter对象的引用, 本质上依旧是多个组件实例共享一个对象, 实际效果以对象的形式直接返回

<!DOCTYPE html>
<html>
<head>
  <title>Vue</title>
</head>

<body>
  <div id="app">
    <button-counter></button-counter>
    <button-counter></button-counter>
    <button-counter></button-counter>
  </div>
</body>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
<script type="text/javascript">
  let counter = {
    count: 0;
  }
  Vue.component("button-counter", {
    data: function() {
      return counter;
    },
    template: `<button v-on:click="count++">You clicked me {{count}} times.</button>`
  })
  let vm = new Vue({
    el: "#app"
  })
</script>
</html>
复制代码

所以为了规避这种现象, 在组件化实现的时候, data属性必须以函数的形式返回, 以便每个实例可以维护一份被返回对象的独立的拷贝, 而不是共享同一个对象的引用

<!DOCTYPE html>
<html>
<head>
  <title>Vue</title>
</head>

<body>
  <div id="app">
    <button-counter></button-counter>
    <button-counter></button-counter>
    <button-counter></button-counter>
  </div>
</body>
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.js"></script>
<script type="text/javascript">
  Vue.component("button-counter", {
    data: function() {
      return {
        count: 0
      }
    },
    template: `<button v-on:click="count++">You clicked me {{ count }} times.</button>`;
  })
  let vm = new Vue({
    el: "#app"
  })
复制代码

猜你喜欢

转载自juejin.im/post/7043423655178534948