|  | 本文参考孙卫琴,杜聚宾所创作的 <<精通Vue.js: Web前端开发技术详解>>一书 
 普通Vue组件按照使用范围,可以分为两种:
 (1)全局组件:通过Vue应用实例的component()方法注册,可以直接被其他Vue组件访问。
 (2)局部组件:只有父组件通过components选项注册了一个局部组件,父组件才能访问该局部组件。
 
 无论是全局组件还是局部组件,都具有data、methods、computed和watch等选项,而且和根组件一样,也具有类似的生命周期以及生命钩子函数。
 1.注册全局组件全局组件可以直接被其他Vue组件访问。例程1的global.html通过Vue应用实例的component()方法注册了一个名为“counter”的全局组件,在根组件的模板中,插入了三个<counter>组件,由此可见,<counter>组件可以被多次重用。
 例程1  global.html
 
 
 | <div id="app"> <p>计数器1:<counter></counter> </p>
 <p>计数器2:<counter></counter> </p>
 <p>计数器3:<counter></counter> </p>
 </div>
 
 <script>
 const app=Vue.createApp({ })
 
 //注册一个名为counter的组件
 app.component('counter', {
 data() {
 return {   count: 0  }
 },
 template: '<button @click="count++">{{ count }} 次</button>'
 })
 app.mount('#app')
 </script>
 | 
 通过浏览器访问global.html,会得到如图1所示的网页。多次点击网页上的三个按钮,会看到每个计数器的取值都不一样。这是因为每个<counter>组件都有独立的count变量。
 
   图1  global.html的网页
 
 在例程2的globalscope.html中,有两个全局组件<wrapper>和<counter>。<counter>组件插入到<wrapper>组件的模板中,<wrapper>组件又插入到根组件的模板中。
 
 例程2  globalscope.html
 
 
 | <div id="app"> <wrapper></wrapper>
 </div>
 
 <script>
 const app=Vue.createApp({ })
 
 //定义一个名为counter的组件
 app.component('counter', {
 data() {
 return {   count: 0  }
 },
 template: '<button @click="count++">{{ count }} 次</button>'
 })
 
 //定义一个名为wrapper的组件
 app.component('wrapper', {
 template: `<p>计数器1:<counter></counter></p>
 <p>计数器2:<counter></counter></p>
 <p>计数器3:<counter></counter></p>`
 })
 app.mount('#app')
 </script>
 | 
 在JavaScript中,单行字符串可以用符号“'”或“`”来引用。如果是多行字符串,只能用符号“`”来引用。例如globalscope.html中<wrapper>组件的template选项的模板字符串就用符号“`”来引用。
 
 2.注册局部组件在介绍局部组件之前,先分析全局组件的优势和劣势,从而揭示Vue引入局部组件的必要性和它的优势。全局组件可以直接插入到其他组件的模板中,这使得其他组件可以很方便地访问全局组件。但是全局组件也有一个弊端:当浏览器访问一个网页时,会把所有全局组件的代码也下载到客户端。假定某个网页并不包含所有的全局组件,那么下载所有全局组件的代码是多余的,会给网络传输带来额外的负担,降低网站的访问性能。
 为了克服全局组件的弊端,Vue引入了局部组件,局部组件只有在需要被访问的情况下才会下载到客户端,这样就能减轻网络的传输负荷,提高网站的访问性能。
 
 定义以及注册局部组件的步骤如下。
 (1)定义局部组件的内容,例如以下代码定义了三个变量,它们分别表示三个局部组件的内容:
 
 
 | const ComponentA = { /* ... */
 }
 const ComponentB = {
 /* ... */
 }
 const ComponentC = {
 /* ... */
 }
 | 
 (2)在需要访问局部组件的父组件中通过components选项来注册局部组件。例如以下代码在根组件中注册了三个局部组件,这三个局部组件仅对根组件可见,因此根组件就是这三个局部组件的父组件:
 
 
 | const app = Vue.createApp({ components: {   //根组件的components选项
 'component-a': ComponentA,
 'component-b': ComponentB,
 'component-C': ComponentC,
 }
 })
 | 
 例程3的local.html演示了局部组件的基本用法。在local.html中,根组件作为父组件,注册了一个子组件“counter”,在根组件的模板中就能使用这个<counter>子组件。
 
 例程3  local.html
 
 
 | <div id="app"> <p>计数器1:<counter></counter></p>
 <p>计数器2:<counter></counter></p>
 <p>计数器3:<counter></counter></p>
 </div>
 
 <script>
 //定义一个局部组件的内容
 const localComponent={
 data() {
 return {   count: 0  }
 },
 template: '<button @click="count++">{{ count }} 次</button>'
 }
 
 const app=Vue.createApp({
 components: {  //注册counter局部组件
 'counter' : localComponent
 }
 })
 
 const vm=app.mount('#app')
 </script>
 | 
 局部组件只有注册到一个父组件中,才能被这个父组件访问。例如在以下代码中,组件ComponentBase中注册了组件ComponentSub,组件ComponentBase就是组件ComponentSub的父组件,在组件ComponentBase的模板中就能插入组件ComponentSub:
 
 
 | const ComponentSub = { /* ... */
 }
 
 const ComponentBase = {
 components: {  //注册ComponentSub组件
 'ComponentSub': ComponentSub
 },
 template: '<ComponentSub></ComponentSub>'
 }
 | 
 在例程4的localscope.html中,<counter>是局部组件,<wrapper>是全局组件。
 
 例程4  localscope.html
 
 
 | <div id="app"> <wrapper />
 </div>
 
 <script>
 //定义一个局部组件的内容
 const localComponent={……}
 
 const app=Vue.createApp({
 components: {  //注册counter局部组件,仅对根组件可见
 'counter' : localComponent
 }
 })
 
 //定义一个名为wrapper的全局组件
 app.component('wrapper', {
 template: `<p>计数器1:<counter></counter> </p>
 <p>计数器2:<counter></counter> </p>
 <p>计数器3:<counter></counter> </p>`
 })
 const vm=app.mount('#app')
 </script>
 | 
 尽管在根组件中注册了<counter>组件,但是在<wrapper>组件中并没有注册<counter>组件。<wrapper>组件的模板试图插入<counter>组件,这会导致Vue在编译<wrapper>组件的模板时产生错误。修改这个错误的方法是在<wrapper>组件中先注册<counter>组件:
 
 
 | app.component('wrapper', { components: {  //注册counter局部组件,仅对<wrapper>组件可见
 'counter' : localComponent
 },
 ……
 })
 | 
 程序猿的技术大观园:www.javathinker.net
 |  |