• Vue基础篇--8组件基础 component


    Vue基础篇--8组件基础 component

    1.简单示例

    <div id='components1'>
    	<button-conter></button-conter>
    </div>
    
    <script>
    	// 定义一个名为button-conter组件
    	Vue.component("button-conter",{
    		data:function () {
    			return {
    				count:0
    			}
    		},
    		template:`<button v-on:click="count++">You clicked me {{count}}</button>`
    	});
    	// 创建一个根实例
    	new Vue({el:"#components1"})
    </script>
    
    • 组件是可以复用的,这样你在id='components1'的作用域中再定义<button-conter></button-conter>也是可以的,并且它们彼此之间互不影响。
    • 因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 datacomputedwatchmethods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。

    2.组件的复用

    • 你可以将组件进行任意次数的复用:
    <div id="components-demo">
      <button-counter></button-counter>
      <button-counter></button-counter>
      <button-counter></button-counter>
    </div>
    

    注意: 当点击按钮时,每个组件都会各自独立维护它的 count。因为你每用一次组件,就会有一个它的新实例被创建。

    data必须是一个函数

    • 当我们定义这个 `` 组件时,你可能会发现它的 data 并不是像这样直接提供一个对象:
    data: {
      count: 0
    }
    

    取而代之的是,一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:

    data: function () {
      return {
        count: 0
      }
    }
    

    3.组件的组织

    • 通常一个应用会以一颗嵌套的组件树的形式来组织

      例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。

      为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册局部注册。至此,我们的组件都只是通过 Vue.component 全局注册的:

      Vue.component('my-component-name', {
        // ... options ...
      })
      

      全局注册的组件可以用在其被注册之后的任何 (通过 new Vue) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。

      到目前为止,关于组件注册你需要了解的就这些了,如果你阅读完本页内容并掌握了它的内容,我们会推荐你再回来把组件注册读完。

    4.通过 Prop 向子组件传递数据

    • Prop 是你可以在组件上注册的一些自定义 attribute。当一个值传递给一个 prop attribute 的时候,它就变成了那个组件实例的一个属性。为了给博文组件传递一个标题,我们可以用一个 props 选项将其包含在该组件可接受的 prop 列表中:
    Vue.component('blog-post', {
      props: ['title'],
      template: '<h3>{{ title }}</h3>'
    })
    

    一个组件默认可以拥有任意数量的 prop,任何值都可以传递给任何 prop。在上述模板中,你会发现我们能够在组件实例中访问这个值,就像访问 data 中的值一样。

    一个 prop 被注册之后,你就可以像这样把数据作为一个自定义 attribute 传递进来:

    <blog-post title="My journey with Vue"></blog-post>
    <blog-post title="Blogging with Vue"></blog-post>
    <blog-post title="Why Vue is so fun"></blog-post>
    

    然而在一个典型应用中,你可能在data里有一个博文数组:

    <div id='components1'>
    	<button-conter></button-conter>
    	<blog-post v-for="post in posts"
    	v-bind:title="post.title"
    	v-bind:key="post.id"
    	></blog-post>
    </div>
    
    // 定义一个名为button-conter组件
    Vue.component("button-conter",{
    	data:function () {
    		return {
    			count:0,
    		}
    	},
    	template:`<button v-on:click="count++">You clicked me {{count}}</button>`
    });
    Vue.component("blog-post",{
    	props:['title'],
    	template:`<h3>{{title}}</h3>`
    })
    
    
    
    // 创建一个根实例
    new Vue({el:"#components1",
    data:{
    	posts:[
    		{id:1,title:"My journey with Vue"},
    		{id:2,title:"Blogging with Vue"},
    		{id:3,title:"Why Vue is so fun"},
    	]
    }
    })
    

    如上所示,你会发现我们可以使用 v-bind 来动态传递 prop。这在你一开始不清楚要渲染的具体内容,比如从一个 API 获取博文列表的时候,是非常有用的。

    5.单个根元素

    • 当构建一个 <blog-post> 组件时,你的模板最终会包含的东西远不止一个标题:

      最最起码,你会包含这篇博文的正文:

    <h3>{{ title }}</h3>
    <div v-html="content"></div>
    

    然而如果你在模板中尝试这样写,Vue 会显示一个错误,并解释道 every component must have a single root element (每个组件必须只有一个根元素)。你可以将模板的内容包裹在一个父元素内,来修复这个问题,例如:

    <div class="blog-post">
      <h3>{{ title }}</h3>
      <div v-html="content"></div>
    </div>
    

    看起来当组件变得越来越复杂的时候,我们的博文不只需要标题和内容,还需要发布日期、评论等等。为每个相关的信息定义一个 prop 会变得很麻烦:

    <blog-post
      v-for="post in posts"
      v-bind:key="post.id"
      v-bind:title="post.title"
      v-bind:content="post.content"
      v-bind:publishedAt="post.publishedAt"
      v-bind:comments="post.comments"
    ></blog-post>
    

    所以是时候重构一下这个<blog-post>组件了,让它变成接受一个单独的 post prop:

    <blog-post
      v-for="post in posts"
      v-bind:key="post.id"
      v-bind:post="post"
    ></blog-post>
    
    Vue.component('blog-post', {
      props: ['post'],
      template: `
        <div class="blog-post">
          <h3>{{ post.title }}</h3>
          <div v-html="post.content"></div>
        </div>
      `
    })
    

    上述的这个和一些接下来的示例使用了 JavaScript 的模板字符串来让多行的模板更易读。它们在 IE 下并没有被支持,所以如果你需要在不 (经过 Babel 或 TypeScript 之类的工具) 编译的情况下支持 IE,请使用折行转义字符取而代之。

    现在,不论何时为 post 对象添加一个新的属性,它都会自动地在 <blog-post> 内可用。

    6.监听子组件事件

    • 在我们开发<blog-post>组件时,它内部一些功能要求我们和父级组件进行沟通。比如在父组件定义字体大小,子组件中 引入一个辅助功能来放大博文的字号 ,同时页面其他字号保持默认

    • 示例:

      <div id='components1'>
          <!--在父组件中,我们添加一个postFontSize数据属性来支持这个功能-->
          <!--通过 v-on:enlarge-text="postFontSize += 0.1" 监听器,父级组件就会接收该事件并更新 postFontSize 的值-->
      	<div :style="{fontSize:postFontSize + 'em'}">
      		<blog-post v-for="post in posts"
      		v-bind:post="post"
      		v-bind:key="post.id"
      		v-on:enlarge-text="postFontSize += 0.1"
      		></blog-post>
      	</div>
      </div>
      
      Vue.component("blog-post",{
      	props:['post'],
          // 每篇博文正文之前添加一个按钮来放大字号
          // 同时子组件调用内建$emit方法传入事件名称
      	template:`<div class="blog-post">
      		<h3>{{post.title}}</h3>
      		<button v-on:click="$emit('enlarge-text')">Enlarge text</button>
      		<div v-html="post.content"></div>
      	</div>`
      })
      
      
      
      // 创建一个根实例
      new Vue({el:"#components1",
      data:{
      	posts:[
      		{id:1,title:"My journey with Vue",content:"<span>文章1</span>"},
      		{id:2,title:"Blogging with Vue",content:"<span>文章2</span>"},
      		{id:3,title:"Why Vue is so fun",content:"<span>文章3</span>"},
      	],
          // 定义默认字体大小
      	postFontSize:1
      }
      })
      
      

    使用事件抛出一个值

    • 例如我们想让<blog-post>组件决定它的文本要放大多少,可以通过使用$emit第二个参数提供这个值

      <!--子组件定义传入放大的大小-->
      <button v-on:click="$emit('enlarge-text', 0.1)">
        Enlarge text
      </button>
      

      然后当父组件监听这个事件时候,我们通过$event 访问抛出这个值:

      <blog-post
        ...
        v-on:enlarge-text="postFontSize += $event"
      ></blog-post>
      
    • 又或用函数去处理这个事件:

      <blog-post
        ...
        v-on:enlarge-text="onEnlargeText"
      ></blog-post>
      
      // 那么这个值将会作为第一个参数传入这个方法
      methods: {
        onEnlargeText: function (enlargeAmount) {
          this.postFontSize += enlargeAmount
        }
      }
      

    在组件上使用v-model

    • 自定义事件也可以用于创建支持 v-model 的自定义输入组件。

      <input v-model="searchText">
      
    • 等价于

      <input
        v-bind:value="searchText"
        v-on:input="searchText = $event.target.value"
      >
      
    • 当用在组件上时,v-model 则会这样:

    <custom-input
      v-bind:value="searchText"
      v-on:input="searchText = $event"
    ></custom-input>
    

    为了让它正常工作,这个组件内的 `` 必须:

    • 将其 value attribute 绑定到一个名叫 value 的 prop 上
    • 在其 input 事件被触发时,将新的值通过自定义的 input 事件抛出

    写成代码之后是这样的:

    Vue.component('custom-input', {
      props: ['value'],
      template: `
        <input
          v-bind:value="value"
          v-on:input="$emit('input', $event.target.value)"
        >
      `
    })
    

    现在 v-model 就应该可以在这个组件上完美地工作起来了:

    <custom-input v-model="searchText"></custom-input>
    

    7.通过插槽分发内容

    • 和 HTML 元素一样,我们经常需要向一个组件传递内容,像这样:
    <div id="demo">
            <alert-box>
                Something bad happened
            </alert-box>
    </div>
    
    Vue.component("alert-box",{
            template:`
                <div class="demo-alert-box">
                    你好啊!
                </div>
            `
        });
        new Vue({el:"#demo"})
    
    • 我们定义<alert-box>内的内容并没有打印出来,此时你只需要加入<slot></slot>,这样内容都会打印出来。

      Vue.component("alert-box",{
              template:`
                  <div class="demo-alert-box">
                      你好啊!
                      <slot></slot>
                  </div>
              `
          });
          new Vue({el:"#demo"})
      

    8.动态组件

    <div id="app">
        <button @click="change">切换</button>
        <component :is="type"></component>
    </div>
    
    Vue.component("One",{
        template:"<span>One</span>"
    });
    Vue.component("Two",{
        template:"<span>Two</span>"
    });
    new Vue({
        el:"#app",
        data:{
            type:"One"
        },
        methods:{
            change:function () {
                this.type = (this.type === "One"?"Two":"One")
            }
        }
    })
    

    9.解析 DOM 模板时的注意事项

    • 有些 HTML 元素,诸如 ,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 、 和 ,只能出现在其它某些特定的元素内部。

      这会导致我们使用这些有约束条件的元素时遇到一些问题。例如:

    <table>
      <blog-post-row></blog-post-row>
    </table>
    

    这个自定义组件 <blog-post-row>会被作为无效的内容提升到外部,并导致最终渲染结果出错。幸好这个特殊的 is attribute 给了我们一个变通的办法:

    <table>
      <tr is="blog-post-row"></tr>
    </table>
    

    参照文献:Vue.js组件基础

  • 相关阅读:
    Java Web系统经常使用的第三方接口
    ExtJS笔记--applyTo和renderTo的差别
    ORACLE触发器具体解释
    java多线程样例
    RapeLay(电车之狼R)的结局介绍 (隐藏结局攻略)
    排序——选择排序
    常见hash算法的原理
    jdk和jre是什么?都有什么用?(转帖)
    Ubuntu下deb包的安装方法
    參加《全流程全要素的研发项目管理》培训记录与心得
  • 原文地址:https://www.cnblogs.com/xujunkai/p/12215961.html
Copyright © 2020-2023  润新知