VUE2中文文档:组件基础篇

组件基础

组件(component),是具有 name 名称的可复用 Vue 实例:当前示例中是 <button-counter>。我们可以使用 new Vue 创建出一个 Vue 根实例,然后将这个组件作为其中的一个自定义元素(custom element)。

由于组件是可复用的 Vue 实例,它们接收的选项,和在 new Vue 时候的选项相同,例如 datacomputedwatchmethods 和生命周期钩子。唯一的例外是,类似 el 这样,根实例上特有(root-specific)的选项。

data 必须是一个函数

组件的 data 选项必须是一个函数,以便每个实例都可以维护「函数返回的数据对象」的彼此独立的数据副本,

如果 Vue 没有遵循这个规定,点击其中一个按钮,会影响其他所有用到此 data 的组件实例

组件注册有两种方式:全局注册和局部注册。

全局方式注册的组件,可以用于之后创建的所有(通过 new Vue 创建的)Vue 根实例,以及 Vue 实例组件树中所有子组件的内部。

使用 props 向子组件传递数据

new Vue({
  el: '#blog-post-demo',
  data: {
    posts: [
      { id: 1, title: '我的 Vue 旅程' },
      { id: 2, title: '用 Vue 写博客' },
      { id: 3, title: 'Vue 如此有趣' },
    ]
  }
})

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

使用 events 向父组件发送消息

new Vue({
  el: '#blog-posts-events-demo',
  data: {
    posts: [/* ... */],
    postFontSize: 1                          //定义一个对象用作字体大小
  }
})

<div id="blog-posts-events-demo">
  <div :style="{ fontSize: postFontSize + 'em' }">        //将style属性动态的绑定起来,一旦数据传入可以及时更新
    <blog-post
      v-for="post in posts"
      v-bind:key="post.id"
      v-bind:post="post"
      v-on:enlarge-text="postFontSize += 0.1"            //监听enlarge-text事件,触发则执行。
    ></blog-post>
  </div>
</div>
Vue.component('blog-post', {
  props: ['post'],
  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>
  `
})

在 event 事件中发送一个值

有时,想在 event 事件中发送一个特定的值。例如,我们可能想要在 <blog-post> 组件自身内部,去控制放大文本字号的间隔。在这种情况下,我们可以使用 $emit 的第二个参数来提供字号间隔值:

<button v-on:click="$emit('enlarge-text', 0.1)">
  放大文本
</button>

<blog-post
  ...
  v-on:enlarge-text="postFontSize += $event"               //此时$event就是传入的值0.1
></blog-post>

或者,如果事件处理函数是一个方法:

<blog-post
  ...
  v-on:enlarge-text="onEnlargeText"
></blog-post>

methods: {
  onEnlargeText: function (enlargeAmount) {              //此时$event传入的值会作为方法的第一个参数,这里是enlargeAmount
    this.postFontSize += enlargeAmount
  }
}

在组件中使用 v-model

自定义事件(custom event),还可以用来创建出「实现 v-model 机制的自定义输入框(custom input)」

<input v-model="searchText">

等同于如下:                             //完全意义上的等同   <input v-bind:value="searchText"                   //绑定value和searchText的值(即随着searchText实时更新value) v-on:input="searchText = $event.target.value"        //将value值赋值给searchText >                                   //以上便实现了searchText和value的双向绑定    

而用于一个组件时,也是如此。

为了组件内部能够有效运行,组件内的 <input> 必须:

将 value 属性绑定到 value prop
在 input 输入框中,在自定义的 input 事件中,发送一个新的值

这里就是上面所描述的:

Vue.component('custom-input', {
  props: ['value'],                                 //2.接受父组件传递的value值
  template: `
    <input
      v-bind:value="value"                             //3.将收到的value赋值给input框的value
      v-on:input="$emit('input', $event.target.value)             //4.监听input,并向父组件返回名为input的事件以及当前DOM的value
    >
  `
})

<custom-input v-bind:value="
searchText"                           //1.将searchText绑定到value v-on:input="searchText = $event"                       //5.接受子组件触发input,将子组件传递的value赋值给searchText ></custom-input>
                                        //以上五点即有效实现了子组件和父组件完全复刻,也就是说v-modle在父组件也可以用了

所以,父组件用更简洁的形式替代如下。
<custom-input v-model="searchText"></custom-input>
 

使用 slots 进行内容分发

通过 Vue 的 <slot> 自定义元素,可以非常简单的实现这个任务:

Vue.component('alert-box', {
  template: `
    <div class="demo-alert-box">
      <strong>Error!</strong>
      <slot></slot>
    </div>
  `
})

<alert-box>
  发生一些错误。
</alert-box>

会被渲染为如下结果:

动态组件

 通过向 Vue 的 <component> 元素传入 is 特性,

<!-- Component changes when currentTabComponent changes -->
<component v-bind:is="currentTabComponent"></component>

通过改变:is的值就可以改变组件的选择。                          //话说这难道不是vue-router?

DOM 模板解析注意事项

有些 HTML 元素,例如 <ul><ol><table> 和 <select> 这些元素,会对于出现在其内部的元素有所限制;而另一些 HTML 元素,例如 <li><tr> 和 <option> 这些元素,只可以出现在前面那些元素的内部。

由于这种 HTML 运行机制,在这些受限制的元素内部使用组件,会导致一些问题。

自定义组件 <blog-post-row> 会被当作无效内容,提升到 table 元素之外,从而导致最终渲染输出后的错误。幸运的是,is 特性提供了一种解决方案:

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

应当注意,在使用以下字符串模板之一的场景中,这些限制将不再适用

字符串模板(例如 template: '...'
单文件 (.vue) 组件
<script type="text/x-template">

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注