注意,在为组件添加数据时,data不再是对象了,而是function,而且要通过 return的形式进行返回;否则,页面上是无法看到效果的。通过 function返回对象的形式来定义data,作用是:
上方代码中,组件<account>被调用了两次(不像根组件那样只能调用一次),但是每个组件里的数据 myData是各自独立的,不产生冲突。
换而言之,通过函数返回对象的目的,是为了让每个组件都有自己独立的数据存储,而不应该共享一套数据。
为什么组件的data必须是一个function
我们先来看下面这样的例子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="https://www.jb51.net/vue2.5.16.js"></script> </head> <body> <div> <!-- 第一次调用组件 --> <counter></counter> <hr> <!-- 第二次调用组件 --> <counter></counter> </div> <!-- 定义模板 --> <template> <div> <input type="button" value="让count加1" @click="increment"> <h3>{{count}}</h3> </div> </template> <script> var dataObj = { count: 0 } // 这是一个计数器的组件, 身上有个按钮,每当点击按钮,让 data 中的 count 值 +1 Vue.component('counter', { template: '#tmpl', data: function () { return dataObj //当我们return全局的dataObj的时候,子组件们会共享这个dataObj }, methods: { increment() { this.count++ } } }) // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: {}, methods: {} }); </script> </body> </html>
运行效果如下:
上面的例子中,将组件<counter>调用了两次,由于dataObj是全局对象,导致两个组件实例都可以共享这个dataObj数据。于是,我们点击任何一个组件实例的按钮,都可以让count数据加1。
现在问题来了,如果我们想让组件<counter>的两个实例去单独操作count数据,应该怎么做呢?我们应该修改 data中 return出去的内容:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="https://www.jb51.net/vue2.5.16.js"></script> </head> <body> <div> <counter></counter> <hr> <counter></counter> <hr> <counter></counter> </div> <template> <div> <input type="button" value="让count加1" @click="increment"> <h3>{{count}}</h3> </div> </template> <script> var dataObj = { count: 0 } // 这是一个计数器的组件, 身上有个按钮,每当点击按钮,让 data 中的 count 值 +1 Vue.component('counter', { template: '#tmpl', data: function () { // return dataObj //当我们return全局的dataObj的时候,这个dataObj是共享的 return { count: 0 } // 【重要】return一个**新开辟**的对象数据 }, methods: { increment() { this.count++ } } }) // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: {}, methods: {} }); </script> </body> </html>
运行效果:
如上图所示,每当我们创建一个新的组件实例时,就会调用data函数,data函数里会return一个新开辟的对象数据。这样做,就可以保证每个组件实例有独立的数据存储。
组件的切换
使用v-if和v-else结合flag进行切换
代码举例:(登录组件/注册组件,二选一)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script src="https://www.jb51.net/vue2.5.16.js"></script> </head> <body> <div> <!-- 温馨提示:`.prevent`可以阻止超链接的默认事件 --> <a href="" @click.prevent=" flag=true">登录</a> <a href="" @click.prevent=" flag=false">注册</a> <!-- 登录组件/注册组件,同时只显示一个 --> <login v-if="flag"></login> <register v-else="flag"></register> </div> <script> Vue.component('login', { template: '<h3>登录组件</h3>' }) Vue.component('register', { template: '<h3>注册组件</h3>' }) // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: { flag: false }, methods: {} }); </script> </body> </html>
运行效果如下:
使用Vue提供的<component>标签实现组件切换
上面的例子中,我们是通过flag的值来进行组件的切换。但是,flag的值只可能有两种情况,也就是说,v-if和v-else只能进行两个组件之间的切换。
那如何实现三个甚至三个以上的组件切换呢?这里,我们可以用到Vue提供的<component>标签。
我们先来看一下<component>标签的用法。
基于上面的代码,如果我想让login组件显示出来,借助<component>标签可以这样做: