组件(Component)是Vue.js最核心的功能。
组件与Vue类似需要注册之后才可以使用。
注册有全局注册和局部注册两种方式。全局注册后在任何Vue实例中都可以使用。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="vue.min.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> </head> <body> <div id="app"> <my-component></my-component> <!--组件当作一个新的标签来使用--> </div> <script> // 全局组件 // 注册 Vue.component ('my-component',{ template: '<div>组件测试001</div>' //template的DOM结构必须被一个元素包裹着,否则无法显示 }); var app = new Vue({ el: "#app", }) </script> </body> </html>
需要注意的是:template的DOM结构必须被一个元素包含,否则无法渲染。
在Vue实例中,使用components选项可以局部注册组件,注册后的组件只有在该实例作用域下有效。
同时组件中也可以使用components选项来注册组件。
除了template选项外,组件中还可以像Vue实例那样使用其它选项,比如data、computed、methods等
在使用data的时候,必须是以函数的形式,将数据return出来。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="vue.min.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> </head> <body> <div id="app"> <my-component></my-component> </div> <script> Vue.component('my-component',{ template: '<div>{{ message }}</div>', data: function () { return { message: '组件中可以使用data、computed、methods等,但是使用data时,data必须是函数,然后将数据return出去' } } }); var app = new Vue({ el: "#app", }) </script> </body> </html>
如果return出的对象引用了外部的一个对象,那么这个对象就是共享的,任何一处修改都会同步。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="vue.min.js"></script> </head> <body> <div id="app"> <my-component></my-component> <my-component></my-component> <my-component></my-component> </div> <script> var data = { counter: 0 }; // data属于全局变量,如果改变了所有组件都会跟着一起改变 Vue.component('my-component',{ template: '<button @click="counter++">{{ counter }}</button>', data: function () { return data; // 在组件中不自定义data,直接引用data.counter那么就是常量,永远为0,这属于两个不同的作用域 } }); var app = new Vue({ el: "#app", //为啥不能将data定义到app这个对象里面来,因为感觉有点多此一举 }); </script> </body> </html>
效果:
有一个修改所有的之都会与之修改。
正确的做法如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="vue.min.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> </head> <body> <div id="app"> <my-component></my-component> <my-component></my-component> <my-component></my-component> </div> <script> Vue.component('my-component',{ template: '<button @click="counter++">{{ counter }}</button>', data: function () { return { counter: 0 }; //每个组件都有一个自己的域 } }); var app = new Vue({ el: "#app", }) </script> </body> </html>
效果:
还有一点需要注意的是:
Vue组件的模板在某些情况下会受到HTML元素的限制,比如table标签内只允许出现tr、td、th
可以使用特殊的is属性来进行挂载。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="vue.min.js"></script> <script src="https://unpkg.com/axios/dist/axios.min.js"></script> </head> <body> <!--<div id="app">--> <!--<table>--> <!--<my-component></my-component>--> <!--</table>--> <!--</div>--> <!--<div id="app"><div>组件测试001</div><table></table></div>--> <!--其实并没有渲染进去--> <div id="app"> <table is="my-component"></table> </div> <!--<div id="app"><div>组件测试001</div></div>--> <!--tbody在渲染时会替换组件的内容--> <!--常见的限制性元素:<ul> <ol> <select>--> <script> Vue.component ('my-component',{ template: '<div>组件测试001</div>' }); var app = new Vue({ el: "#app", }) </script> </body> </html>