认识组件化

将一个html拆解,分成很多个组件,每个组件实现页面的一个功能块,每个组件里面又可以细分,就是不断抽象的思想,不断把公共的、可以独立拆分出来的抽出来作为一个独立可复用的组件来向上提供调用,这样让我们的代码更加方便组织和管理,并且扩展性也更强。

注册组件

组件的使用有三步:

  1. 在script标签内,创建组件构造器对象,定义组件模板

    我是标题我是内容,11111我是内容,22222`
        })
        ...." _ue_custom_node_="true">
  2. 注册组件(全局组件),在创建Vue实例前


  3. 在html中使用组件


    下面引用网上的一个图:

Vue系列   组件化开发_Vue

注册组件步骤解析

完整的代码:

Vue Demo我是标题我是内容,11111我是内容,22222`
    })

    //2.注册组件
    Vue.component('mycpn', cpnC)

    const app = new Vue({
        el: "#app",
        data: {
            message: 'hello'
        }
    })" _ue_custom_node_="true">
  1. Vue.extend():

调用Vue.extend()创建的是一个组件构造器。

通常在创建组件构造器时,传入template代表我们自定义组件的模板。

该模板就是在使用到组件的地方,要显示的HTML代码。

事实上,这种写法在Vue2.x的文档中几乎已经看不到了,它会直接使用下面我们会讲到的语法糖,但是在很多资   料还是会提到这种方式,而且这种方式是学习后面方式的基础。

  1. Vue.component():

调用Vue.component()是将刚才的组件构造器注册为一个组件,并且给它起一个组件的标签名称。

所以需要传递两个参数:1、注册组件的标签名 2、组件构造器

  1. 组件必须挂载在某个Vue实例下,否则它不会生效。(见下页)

我们来看下面我使用了三次

而第三次其实并没有生效,因为他没有在new Vue挂载的实例#app下

Vue系列   组件化开发_Vue_02

组件其他补充

全局组件和局部组件

当我们通过调用Vue.component()注册组件时,组件的注册是全局的,这意味着该组件可以在任意Vue示例下使用。

如果我们注册的组件是挂载在某个实例中, 那么就是一个局部组件,开发过程常用!


父组件和子组件

Vue Demo知识点1:
	组件构造器1 放在组件构造器2里面注册,而组件构造器2放在Vue实例里注册
    组件2是组件1的父组件
    //知识点3:这里会报错,如果要在这里使用cpn1,可以在Vue实例里再注册下cpn1我是标题1我是内容,11111我是内容,22222`
    })
    //2.创建第二个组件构造器(父组件)
    const cpnC2 = Vue.extend({
        template: `我是标题2我是内容,11111我是内容,22222`,
        components: {
            cpn1: cpnC1    //知识点2:cpn1只能在cpnC2组件里使用(作用域只是在当前组件模板使用),无法在外面(全局)使用,如果要在全局用,可以在Vue实例再注册cpn1即可
        }
    })

    // Vue实例也是一个组件, 相当于root组件
    const app = new Vue({
        el: "#app",
        data: {
            message: 'hello'
        },
        components: {
            cpn2: cpnC2
        }
    })" _ue_custom_node_="true">

解析过程

在#app模板中使用时,cpn2组件已经在组件cpnC2内部编译好了,Vue内部解析编译cpnC2的模板的时候,当解析到,会在当前自己注册的组件内查找是否有注册cpn1组件,如果没找到,再去Vue实例中查找是否有注册cpn1组件,如果Vue实例里也没有,再去全局组件里找,最终找到后,会把cpn1标签替换为组件cpn1中定义的模板,替换后,cpn2组件会编译如下:

    const cpnC2 = Vue.extend({
        template: `我是标题2
                	我是内容,11111
                	我是内容,22222我是标题1
                	我是内容,11111我是内容,22222`,
        components: {
            cpn1: cpnC1    //cpn1只能在cpnC2组件里使用(作用域只是在当前组件模板使用),无法在外面(全局)使用
        }
    })

所以,对于Vue实例来说,Vue实例本身不关心cpn1组件的存在(因为他也不知道),所以当前示例在#app模板中使用cpn1,就会报错

vue.js:634 [Vue warn]: Unknown custom element:- did you register the component correctly? For recursive components, make sure to provide the "name" option.

(found in)

注册组件语法糖

主要是省去调用Vue.extend()的步骤

Vue Demo我是标题cpn1我是内容,cpn1我是内容,cpn1`
    })

    //注册局部组件语法糖
    const app = new Vue({
        el: '#app',
        data: {
            message: 'hello'
        },
        components: {
            'cpn2': {
            template: `我是标题cpn2我是内容,cpn2我是内容,cpn2`               
            }
        }
    })" _ue_custom_node_="true">

模板的分离写法

这里的分离指的是:模板和组件分离

Title
我是cpn1-->

我是cpn2

组件数据存放

模板里面不能直接访问Vue实例data数据, Vue组件的数据存放在组件里

Title{{title}}我是模板的数据

为什么组件data必须是函数

主要是为了解决多个组件实例同时调用data的同一个数据的时候,不会相互影响:

Title当前计数: {{counter}}-+

假设data这里不是函数,即:

Vue.component('cpn', {
  template: '#cpn',
  data: {
    counter: 0
  }
})

这时候就会有一个问题,比如有三个组件实例1,2,3,实例1把counter+1,实例2再去取counter的时候,就会取到counter=1而不是0,三个实例访问的变量counter在内存中是指向同一个地址。

//实例1//实例2//实例3

父子组件通信

父组件通过props向子组件传递数据,子组件通过自定义事件emit Event与父组件发送消息.

Vue实例和子组件的通信和父组件和子组件的通信过程是一样的.

父级向子级传递

基本使用

最简单的props传递过程

1.Vue实例中data

data: {
message: 'hello world!'
},

2.子组件中的props

props: ['message']

3.通过:message="message"将data中的数据传递给props


4.将props中的数据显示在子组件中

//子组件的模板{{message}}

完整案例代码:

Title//子组件的模板{{message}}

案例2:通过props传递数组

Title{{message}}{{cmovies}}{{item}}

props数据验证

Title{{cmessage}}{{cmovies}}{{item}}

上面演示了props选项使用字符串、数组、对象类型的数据验证,props支持的数据类型还有:

  • String

  • Number

  • Boolean

  • Array

  • Object

  • Date

  • Function

  • Symbol

Vue.component('my-component', {
	props: {
		// 基础的类型检查(‘null’ )
		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
			}
		}
	}
})

当我们有自定义构造函数时,验证也支持自定义的类型

function Person(first_name,last_name){
	this.first_name = first_name
	this.last_name = last_name
}

Vue.component('blog-post',{
	props: {
		author: Person
	}
})

子级向父级传递

后面内容明天再更! 加油!

插槽slot