Vue 组件化开发——组件详解
什么是组件化?
- 将一个复杂的问题拆分成很多个可以处理的小问题,再将其放入整体当中,很大的问题也会迎刃而解。
- 组件是构成页面中独立结构单元,主要以页面结构的形式存在。
- 不同组件也具有基本交互功能,根据业务逻辑实现复杂的项目功能。
- 组件化也是类似的思想:
- 如果将一个页面中的所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展。
- 但是如果将一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那之后的整个页面的管理和维护就变得非常容易。
- 组件可以实现复杂的页面结构,提高代码的可复用性。
Vue 组件化思想
- 组件化是 Vuejs 中的重要思想。
- 它提供了一种抽象,让我们可以开发出一个个独立可复用的小组件来构造我们的应用。
- 任何的应用都可以被抽象成一颗组件树。
- 组件化思想的应用:
- 有了组件化的思想,我们在之后的开发中就要充分利用它。
- 尽可能将页面拆分成一个个小的、可复用的组件。
- 这样让我们的代码更加方便组织和管理,并且扩展性也更强。
注册组件的基本步骤
- 组件的使用分为三个步骤:
- 创建组件构造器。
- 注册组件。
- 使用组件。
- 注册组件的步骤:
- 调用 Vue.extend() 方法创建组件构造器。
- 调用 Vue.component() 方法注册组件。
- 在 Vue 实例中的作用范围内使用组件。
<div id="app"> <!-- 3. 使用组件 --> <my-cpn></my-cpn> </div> <script src="../js/vue.js"></script> <script> // 1. 创建组件构造器 const myComponent = Vue.extend({ template: ` <div> <h2>组件标题</h2> <p>我是组件中的一个段落内容</p> </div> ` }) // 2. 注册组件,并且定义组件标签的名称 Vue.component('my-cpn',myComponent) let app = new Vue({ el: 'app' }) </script>
- 查看运行结果:
- 和直接使用一个 div 看起来并没有什么区别。
- 但是我们可以设想,如果很多地方都要显示这样的信息,我们是不是就可以直接使用
<my-cpn></my-cpn>
来完成呢?
注册组件步骤解析
- Vue.extend() :
- 调用 Vue.exted() 创建的是一个组件构造器。
- 通常在创建组件构造器时,传入 template 代表自定义组件的模板。
- 该模板就是在使用到组件的地方,要显示的 HTML 代码。
- 事实上,这种写法在 Vue2.x 的文档中几乎已经看不到了,会直接使用语法糖,但是很多资料话是会提到,而且这种方式也是后面的基础。
- Vue.component() :
- 调用 Vue.component() 是将刚才注册的组件构造器注册为一个组件,并且给他起一个组件的标签名称。
- 所以需要传递两个参数:
- 注册组件的标签名。
- 组件构造器。
- 组件必须挂载在某个 Vue 实例下,否则它不会生效。
- 下面使用三次,第三次不会生效。
<div id="app"> <!-- 3.使用组件 --> <my-cpn></my-cpn> <div> <my-cpn></my-cpn> </div> </div> <!-- 这个并不会渲染出来,因为它没有在new Vue挂载的实例 #app 之下 --> <my-cpn></my-cpn>
全局组件和局部组件
全局组件
- 当通过调用 Vue.component() 注册组件时,组件的注册是全局的。
- 这就意味着该组件可以在任意 Vue 实例下使用。
<div id="app1"> <my-cpn></my-cpn> </div> <div id="app2"> <my-cpn></my-cpn> </div> <script> // 创建组件构造器 const myComponent = Vue.extend({ template: ` <div> <h2>组件标题</h2> <p>组件正文的内容</p> </div> ` }) // 注册组件 Vue.component('my-cpn', myComponent) const app1 = new Vue({ el: '#app1', }) const app2 = new Vue({ el: '#app2', }) </script>
局部组件
- 如果注册的组件是挂载在某个实例中,那么就是一个局部组件。
- 通过 Vue 实例的 components 属性在实例中注册组件。
- 在下面这个例子中,app2 中的组件并没有渲染出来,而且会报错。
<div id="app1"> <my-cpn></my-cpn> </div> <div id="app2"> <my-cpn></my-cpn> </div> <script> // 创建组件构造器 const myComponent = Vue.extend({ template: ` <div> <h2>组件标题</h2> <p>组件正文的内容</p> </div> ` }) const app1 = new Vue({ el: '#app1', // 在实例内部注册组件 components: { 'my-cpn': myComponent // 另外一种写法:myCpn: myComponent,这种写法效果和上面的相同。 // 如果在注册组件的时候使用了驼峰命名,那么在使用的时候需要转换成短横线分隔命名。 } }) const app2 = new Vue({ el: '#app2', // components: { // 'my-cpn': myComponent // } })
父组件和子组件
- 在前面见到了组件树:
- 组件和组件之间存在层级关系。
- 而其中最重要的关系就是父子组件的关系。
2.父子组件关系的代码组成:
<div id="app"> <parent-cpn></parent-cpn> </div> <script> // 创建一个子组件构造器 const childComponent = Vue.extend({ template: ` <div> <p>我是子组件的内容</p> </div> ` }) // 创建一个父组件构造器 const parentComponent = Vue.extend({ template: ` <div> 我是父组件的内容 <h2>我是父组件的一个标题</h2> <child-cpn></child-cpn> </div> `, components: { // 在父组件中注册子组件 'child-cpn': childComponent } }) const app = new Vue({ el: '#app', // 在实例中注册父组件 components: { 'parent-cpn': parentComponent } })
- 父子组件错误用法:
- 当子组件注册到父组件的 components 时,Vue 会编译好父组件的模块。
- 该模板的内容已经决定了父组件将要渲染的 HTML (相当于父组件中已经有了子组件中的内容了。)
- 是只能在父组件中被识别的。
- 类似这种用法,是会被浏览器忽略的。
注册组件语法糖
- 在上面注册组件的方式会有些繁琐。
- 为了简化这个过程,提供了注册的语法糖。
- 主要是省去了调用
Vue.extend()
的步骤,而是可以直接使用一个对象来代替。
全局组件注册语法糖
Vue.component('my-cpn',{ template: ` <div> <h2>组件标题</h2> <p>组件正文的内容</p> </div> ` })
局部组件注册语法糖
// 注册局部组件 let app = new Vue({ el: 'app', components: { 'my-cpn': { template: ` <div> <h2>组件标题</h2> <p>组件正文的内容</p> </div> ` } })
模板的分离写法
- 除了 Vue 组件的注册过程比较复杂,还有 template 模板的写法也比较麻烦。
- 如果将其中的 HTML 分离出来,然后挂载到对应的组件上,必然结构会变得清晰。
- Vue 提供了两种方案来定义 HTML 模块内容。
- 使用标签。
<div id="app"> <my-cpn></my-cpn> </div> <script type="text/x-template" id="myCpn"> <div> <h2>组件标题</h2> <p>组件内容</p> </div> </script> <script> const app = new Vue({ el: '#app', // 注册组件 components:{ myCpn:{ template:'#myCpn' } } }) </script>
使用标签。
<div id="app"> <my-cpn></my-cpn> </div> <template id="myCpn"> <div> <h2>组件标题</h2> <p>组件内容</p> </div> </template> <script> const app = new Vue({ el: '#app', // 注册组件 components: { myCpn: { template: '#myCpn' } } }) </script>
组件可以访问 Vue 实例数据吗?
- 组件是一个单独功能模块的封装。
- 这个模板有属于自己的 HTML 模板,也应该有自己的数据 data。
2.组件不能访问 Vue 实例中的数据,而且即使可以访问,如果把所有的数据都放在 Vue 实例中,Vue 实例就会变得非常臃肿。
- 结论:Vue 组件应该有自己保存数据的地方。
组件数据的存放
- 组件对象也有一个 data 属性(也可以有 methods 等属性)。
- 只是这个 data 必须是一个函数。
- 而且这个函数返回一个对象,对象内部保存着数据。
组件的 data 为什么必须是一个函数?
- 因为函数在每一次调用的时候都会形成一个新的对象,这样就不会对同时使用多次组件的数据产生影响。