Loading

Vue组件

Vue组件

组件需要注册后才可以使用,注册分为全局注册和局部注册。

全局注册

全局注册后任何Vue实例都可以使用,子组件必须在父实例创建前注册。

Vue.component('component-name', {
	template: '<div>{{ message }}</div>',
    data: function () {
    	return {message: '组件内容'}
    }
});

component-name是组件的自定义标签名称,推荐使用小写字母加减号分割的形式命名。

Vue.component方法的第二个参数是一个对象字面量,可以包含templatedatacomputedmethods等选项。其中data定义组件数据,必须是函数;template选项的值必须被一个html元素包裹

局部注册

app = new Vue({
	el: '#app',
    components: {
    	'component-name': {
        	template: ''
        }
    }
});

Vue实例中使用components选项局部注册组件,注册后的组件只在该实例作用域下有效。

组件通信

所谓通信即组件之间传递数据,组件关系可分为父子组件通信、兄弟组件通信、跨级组件通信。

父组件向子组件传递数据

组件的props选项声明从父级接受的数据,props选项既可以是字符串数组也可以是对象。

父级向子组件传递数据,可分为3步:

  1. 父组件使用子组件时,在子组件标签添加数据属性
  2. 子组件props选项声明从父级接受的数据
  3. 在子组件中应用从父级接受的数据
<div id="app">
    <my-component message="来自父组件的数据"></my-component>
</div>

<script>
    Vue.component('my-component', {
    	template: '<div>{{ message }}</div>',
        props: ['message']
    });
    
    var app = new Vue({
    	el: '#app'
    });
</script>

props选项传入一个对象类型,对从父级接受的数据进行校验。

子组件向父组件传递数据

Vue通过自定义事件,实现子组件向父组件传递数据:

  1. 子组件通过$emit(eventName, eventArgument)方法触发自定义事件
  2. 父组件使用子组件时,在子组件标签使用v-on指令监听自定义事件
<div id="app">
    <my-component @shownumber="handleShownumber"></my-component>
    <p>数值:{{ total }}</p>
</div>

<script>
    Vue.component('my-component', {
    	template: '<div @click="handleAdd"></div>',
        data : function () {
        	return {counter : 0};
        },
        methods : {
        	handleAdd: function () {
            	this.counter++;
                this.$emit('shomnumber', this.counter);
            }
        }
    });
    
    var app = new Vue({
    	el: '#app',
        data: {
    		total: 0
    	},
        methods: {
        	handleShownumber: function (total) {
            	this.total = total;
            }
        }    
    });
</script>

可以通过v-model替代步骤2中的v-on的事件监听

<div id="app">
    <my-component v-model="total"></my-component>
    <p>数值:{{ total }}</p>
</div>

<script>
    Vue.component('my-component', {
    	template: '<div @click="handleAdd"></div>',
        data : function () {
        	return {counter : 0};
        },
        methods : {
        	handleAdd: function () {
            	this.counter++;
                this.$emit('shomnumber', this.counter);
            }
        }
    });
    
    var app = new Vue({
    	el: '#app',
        data: {
    		total: 0
    	}
    });
</script>

中央事件总线

  1. 创建空的Vue实例,作为中央事件总线
  2. 子组件触发事件时,指定事件发起者为中央事件总线($emit方法的调用方是中央事件总线实例)
  3. 父组件在mounted钩子函数里监听来自中央事件总线的事件
<div id="app">
    <my-component></my-component>
    <p>数值:{{ total }}</p>
</div>

<script>
    var bus = new Vue();
    
    Vue.component('my-component', {
    	template: '<div @click="handleAdd"></div>',
        data : function () {
        	return {counter : 0};
        },
        methods : {
        	handleAdd: function () {
            	this.counter++;
                bus.$emit('shomnumber', this.counter);
            }
        }
    });
    
    var app = new Vue({
    	el: '#app',
        data: {
    		total: 0
    	},
        mounted: function () {
            	var _this = this;
            	bus.$on('shownumber', function (total) {
                	_this.total = total;
                })
            }
    });
</script>

内容分发:slot

具名插槽

子组件模板中的<slot>标签添加name属性指定插槽名字

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

父组件分发的内容包裹在<template>中,使用 v-slot 指令 指定分发的插槽名字

<base-layout>
  <template v-slot:header>
    <h1>Here might be a page title</h1>
  </template>

  <p>A paragraph for the main content.</p>
  <p>And another one.</p>

  <template v-slot:footer>
    <p>Here's some contact info</p>
  </template>
</base-layout>

<template> 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容 .

v-slot 只能添加在 <template>元素上

作用域插槽

父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的

为了让父级中的插槽内容能访问子组件数据,引入作用域插槽:

  1. 子组件<slot>元素绑定子组件数据
<span>
  <slot v-bind:user="user">
    {{ user.lastName }}
  </slot>
</span>

绑定在 <slot> 元素上的 attribute 被称为插槽 prop

  1. 父组件使用v-slot访问子组件绑定的插槽prop
<current-user>
  <template v-slot:default="slotProps">
    {{ slotProps.user.firstName }}
  </template>
</current-user>

所有插槽prop会绑定到slotProps变量上

posted @ 2020-10-25 15:41  未夏  阅读(137)  评论(0编辑  收藏  举报