vue2.X基础知识四之组件及父子组件通信

一、组件注册

1、在Vue中全局注册

//my-component就是注册的组件自定义标签名,推荐使用小写加减号分割的形式命名
//template的DOM结构必须被一个元素包含(这里是div),否则无法渲染
Vue.component('my-component', {template: '
我是组件
'});
   var app = new Vue({
            //选择元素
            el: "#app"
        });

在html中使用组件:


使用全局注册的时候,组件必须先注册,然后再实例化Vue;全局注册的组件,任何Vue实例都可以使用。

2、在Vue实例中,注册局部组件

注册的局部组件只有在该实例作用域下有效。组件也可以使用components选项来注册组件,使组件可以嵌套。

var child = {
    template: '
局部注册组件的内容
' } var app = new Vue({ el: '#app', components: { 'my-component': child } });

3、组件中的data

组件中的配置选项与Vue实例很类似,在组件中使用data时,data必须是函数,然后将数据return出去,例如:

Vue.component('my-component', {
    		template: '
{{ name }}
', /* 子组件的data必须是一个函数 */ data: function() { return { name: '子组件的数据' } }, methods: { handleClick($event){ $event.target.style.color = 'red'; alert('子组件的click事件'); } } }); var app = new Vue({ el: "#app" });
二、组件通信

    组件不仅仅是要把模板的内容进行复用,更重要的是组件间要进行通信。通常父组件的模板中包含子组件,父组件要正向地向子组件传递数据或参数,子组件接收到后根据参数的不同来渲染不同的内容或执行操作。props的值可以是两种,一种是字符串数组,一种是对象。

1、父组件向子组件传递数据,使用props来实现

    在组件中,使用选项props来声明需要从父级接收的数据。我们来看一个最简单的例子,直接给子组件传递一个字符串:

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

上面代码中,我们给子组件设置了一个自定义的属性message,它的值是父组件想要传递给子组件my-component的值,这里是固定的一个字符串。运行结果如下:

vue2.X基础知识四之组件及父子组件通信_第1张图片

说明:由于html特性不区分大小写,当使用DOM模板时,驼峰命名的props名称要转为短横分隔命名,比如props:['warningText'],在组件定义这个属性时候应该这样写:warning-text="来自父组件的信息" (如果使用的是字符串模板(单个vue文件),可忽略这些限制)

  props中声明的数据与组件data函数return的数据主要区别就是props的来自父级,而data中的是组件自己的数据,作用域是组件本身,这两种数据都可以在模板template及计算属性computed和方法methods中使用

  有时候,传递的数据并不是直接写死的,而是来自父级的动态数据,这时可以使用指令v-bind来动态绑定props的值,当父组件的数据变化时,也会传递给子组件。



         
Vue.component('my-component', {
    		props: ['message'],
    		template: `

子组件自身的数据:{{ name }},

来自父组件的数据:{{ message }}

`, data: function() { return { name: '我是子组件自带的数据' } } }); var app = new Vue({ el: "#app", data: { parentMessage: '我是父组件的message', } });

可以看到,这个例子与上一个例子有个很明显的区别,这里使用v-bind绑定了自定义的属性message的值,message保存了父组件parentMessage的值;子组件通过props接收message保存的值,同时template可以像访问data一样,访问props里面的message;输出效果如下:

vue2.X基础知识四之组件及父子组件通信_第2张图片

注意、如果直接传递数字,布尔值、数组、对象,而且不使用v-bind,传递的仅仅是字符串;例如:

    
                       

props单向数据流

Vue2.X通过props传递数据是单向的,也就是父组件数据变化时会传递给子组件,但是反过来不行。通常在业务中经常会遇到两种需要改变prop的情况,代码如下:


以上两种情况,子组件获取父组件的数据之后随意修改,都不会再影响父组件的数据。


props数据验证

    一般当你的组件需要提供给别人使用时,推荐都进行数据验证;如果传入的值类型不对,就会在控制台弹出警告。例如:

Vue.component('my-component', {
	                    template: '
props的值为数组时,接收父组件数据:{{ propA }},接收数值类型:{{ propD }}
',     props: { // 必须是数字类型 propA: Number, // 必须是字符串或数字类型 propB: [String, Number], // 布尔值,如果没有定义,默认值就是true propC: { type: Boolean, default: true }, //数字,而且是必传 propD: { type: Number, required: true }, //如果是数组或对象,默认值必须是一个函数来返回 propE: { type: Array, default: function () { return []; } }, //自定义一个验证函数 propF: { validator: function (value) { return value > 10; } } } }); var app = new Vue({ el: '#app', data: { parentData: 123, count: 456 } });

以上代码如果我们在子组件里不传入prop-d,就会在控制台报错,因为propD是必传项;验证的type类型可以是:String,Number,Boolean,Object,Array,Function;type也可以是一个自定义构造器,使用instanceof检测。

2、子组件向父组件传递数据,使用自定义事件

 子组件需要向父组件传递数据时,就要用到自定义事件;v-on除了监听DOM事件外, 还可以用于组件之间的自定义事件。

 子组件用$emit来触发事件,父组件用$on()来监听子组件的事件。 父组件可以直接在子组件的自定义标签上使用v-on(语法糖@)来监听子组件触发的自定义事件

总数:{{ total }}

以上代码使用@(v-on)监听子组件的increase和reduce自定义事件,一旦子组件触发了这两个事件,父组件就会立即执行handleGetTotal方法,同时接收子组件传递过来的参数(数据);

		Vue.component('my-component', {
			template: `
				
`, data: function () { return { counter: 0 }; }, methods: { handleIncrease: function () { this.counter++; // 触发自定义的increase事件,同时将自身的counter数据传递过去 this.$emit('increase', this.counter); }, handleReduce: function () { this.counter--; // 触发自定义的reduce事件 this.$emit('reduce', this.counter); } } }); var app = new Vue({ el: '#app', data: { total: 0 }, methods: { handleGetTotal: function (total) { this.total = total; } } });
子组件在按钮上绑定click事件,当点击按钮时,执行自身methods里的方法,这两个方法使用vue实例的$emit来触发自定义事件increase或reduce;

除了用v-on在组件上监听自定义事件外,也可以监听DOM事件,这时可以用.native修饰符表示监听的是一个原生事件,监听的是该组件的根元素。例如:

var app = new Vue({
    el: '#app',
    data: {
	total: 0
    },
    methods: {
		handleGetTotal: function (total) {
		    this.total = total;
		},
		handleClick: function () {
		    alert('监听子组件的原生click事件的处理函数要写在父组件上');
		}
	}
});

Vue 2.X可以在自定义组件上使用v-model指令,示例如下:

总数:{{ total }}

使用v-model指令创建自定义的表单输入组件:

总数:{{ total }}


Vue.component('my-component', {
    		props: ['value'],
    		template: '',
    		methods: {
    			updateValue: function (event) {
    				this.$emit('input', event.target.value);
    			}
    		}
    	});
    	
        var app = new Vue({
            el: "#app",
            data: {
            	total: 0
            },
            methods: {
            	handleReduce: function () {
            		this.total--;
            	}
            }
});

以上代码执行过程个人理解:

通过v-model和props将父组件的total值传递给了input;

 input使用v-bind绑定了父组件传递过来的值;同时绑定了input事件,当输入新的input值时,通过updateValue处理函数

 执行$emit('input', event.target.value)将输入的新值传回给父组件的total;(这里面发生了父组件向子组件传值以及子组件给父组件传值的过程,都得益于v-model)

显示效果如下:

vue2.X基础知识四之组件及父子组件通信_第3张图片


文章说明:本文大部分内容来自书籍 《Vue.js实战》





你可能感兴趣的:(vue,vue)