icon-cookie
The website uses cookies to optimize your user experience. Using this website grants us the permission to collect certain information essential to the provision of our services to you, but you may change the cookie settings within your browser any time you wish. Learn more
I agree
blank_error__heading
blank_error__body
Text direction?

Vue.js 组件

组件(Component)是 Vue.js 最强大的功能之一。

组件可以扩展 HTML 元素,封装可重用的代码。

组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树:

注册一个全局组件语法格式如下:

Vue.component(tagName, options)

tagName 为组件名,options 为配置选项。注册后,我们可以使用以下方式来调用组件:

<tagName></tagName>

全局组件

所有实例都能用全局组件。

全局组件实例

注册一个简单的全局组件 runoob,并使用它:

<divid="app"><runoob></runoob></div><script> // 注册 Vue.component('runoob', { template: '<h1>自定义组件!</h1>' }) // 创建根实例 new Vue({ el: '#app' }) </script>
尝试一下 »

局部组件

我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用:

局部组件实例

注册一个简单的局部组件 runoob,并使用它:

<divid="app"><runoob></runoob></div><script> var Child = { template: '<h1>自定义组件!</h1>' } // 创建根实例 new Vue({ el: '#app', components: { // <runoob> 将只在父模板可用 'runoob': Child } }) </script>
尝试一下 »

Prop

prop 是子组件用来接受父组件传递过来的数据的一个自定义属性。

父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":

Prop 实例

<divid="app"><childmessage="hello!"></child></div><script> // 注册 Vue.component('child', { // 声明 props props: ['message'], // 同样也可以在 vm 实例中像 "this.message" 这样使用 template: '<span>{{ message }}</span>' }) // 创建根实例 new Vue({ el: '#app' }) </script>
尝试一下 »

动态 Prop

类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:

Prop 实例

<divid="app"><div><inputv-model="parentMsg"><br><childv-bind:message="parentMsg"></child></div></div><script> // 注册 Vue.component('child', { // 声明 props props: ['message'], // 同样也可以在 vm 实例中像 "this.message" 这样使用 template: '<span>{{ message }}</span>' }) // 创建根实例 new Vue({ el: '#app', data: { parentMsg: '父组件内容' } }) </script>
尝试一下 »

以下实例中使用 v-bind 指令将 todo 传到每一个重复的组件中:

Prop 实例

<divid="app"><ol><todo-itemv-for="item in sites"v-bind:todo="item"></todo-item></ol></div><script> Vue.component('todo-item', { props: ['todo'], template: '<li>{{ todo.text }}</li>' }) new Vue({ el: '#app', data: { sites: [ { text: 'Runoob' }, { text: 'Google' }, { text: 'Taobao' } ] } }) </script>
尝试一下 »

注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。

Prop 验证

组件可以为 props 指定验证要求。

为了定制 prop 的验证方式,你可以为 props 中的值提供一个带有验证需求的对象,而不是一个字符串数组。例如:

Vue.component('my-component',{
  props:{// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
    propA:Number,// 多个可能的类型
    propB:[String,Number],// 必填的字符串
    propC:{
      type:String,
      required:true},// 带有默认值的数字
    propD:{
      type:Number,default:100},// 带有默认值的对象
    propE:{
      type:Object,// 对象或数组默认值必须从一个工厂函数获取default:function(){return{ message:'hello'}}},// 自定义验证函数
    propF:{
      validator:function(value){// 这个值必须匹配下列字符串中的一个return['success','warning','danger'].indexOf(value)!==-1}}}})

当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告。

type 可以是下面原生构造器:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

type 也可以是一个自定义构造器,使用 instanceof 检测。


自定义事件

父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!

我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:

  • 使用 $on(eventName) 监听事件
  • 使用 $emit(eventName) 触发事件

另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。

以下实例中子组件已经和它外部完全解耦了。它所做的只是触发一个父组件关心的内部事件。

实例

<divid="app"><divid="counter-event-example"><p>{{ total }}</p><button-counterv-on:increment="incrementTotal"></button-counter><button-counterv-on:increment="incrementTotal"></button-counter></div></div><script> Vue.component('button-counter', { template: '<buttonv-on:click="incrementHandler">{{ counter }}</button>', data: function () { return { counter: 0 } }, methods: { incrementHandler: function () { this.counter += 1 this.$emit('increment') } }, }) new Vue({ el: '#counter-event-example', data: { total: 0 }, methods: { incrementTotal: function () { this.total += 1 } } }) </script>
尝试一下 »

如果你想在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on 。例如:

<my-componentv-on:click.native="doTheThing"></my-component>

data 必须是一个函数

上面例子中,可以看到 button-counter 组件中的 data 不是一个对象,而是一个函数:

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

这样的好处就是每个实例可以维护一份被返回对象的独立的拷贝,如果 data 是一个对象则会影响到其他实例,如下所示:

实例

<divid="components-demo3"class="demo"><button-counter2></button-counter2><button-counter2></button-counter2><button-counter2></button-counter2></div><script> var buttonCounter2Data = { count: 0 } Vue.component('button-counter2', { /* data: function () { // data 选项是一个函数,组件不相互影响 return { count: 0 } }, */ data: function () { // data 选项是一个对象,会影响到其他实例 return buttonCounter2Data }, template: '<buttonv-on:click="count++">点击了 {{ count }} 次。</button>' }) new Vue({ el: '#components-demo3' }) </script>
尝试一下 »
Measure
Measure
Related Notes
Get a free MyMarkup account to save this article and view it later on any device.
Create account

End User License Agreement

Summary | 7 Annotations
实例选项中注册局部组件
2020/06/01 11:18
接受父组件传递过来的数据的一个自定义属性
2020/06/01 11:19
v-bind 绑定 HTML 特性到一个表达式
2020/06/01 11:19
props 指定验证要求
2020/06/01 11:20
使用 $on(eventName) 监听事件
2020/06/01 11:42
使用 $emit(eventName) 触发事件
2020/06/01 11:42
每个实例可以维护一份被返回对象的独立的拷贝
2020/06/01 11:46