目标 1. 深入理解Vue的组件化机制 2. 掌握Vue组件化常用技术 3. 能够设计并实现多种类型的组件 4. 加深对一些vue原理的理解 5. 学会看开源组件库源码

知识点 1. 组件通信方式盘点 2. 组件复合 3. 递归组件 4. 组件构造函数和实例 5. 渲染函数 6. 组件挂载

组件化

vue组件系统提供了一种抽象,让我们可以使用独立可复用的组件来构建大型应用,任意类型的应用界 面都可以抽象为一个组件树。组件化能提高开发效率,方便重复使用,简化调试步骤,提升项目可维护 性,便于多人协同开发。

组件通信常用方式

props

eventbus

vuex

自定义事件($emit)

边界情况 $parent $children $root $refs provide/inject

非prop特性 $attrs $listeners

组件通信

props

父给子传值

// child
props: { msg: String }
// parent
<HelloWorld msg="Welcome to Your Vue.js App"/>

自定义事件

子给父传值

// child
this.$emit('add', good)
// parent
<Cart @add="cartAdd($event)"></Cart>

事件总线

任意两个组件之间传值常用事件总线 或 vuex的方式。

// Bus:事件派发、监听和回调管理
class Bus {
constructor(){
this.callbacks = {}
}
$on(name, fn){
this.callbacks[name] = this.callbacks[name] || []
this.callbacks[name].push(fn)
}
$emit(name, args){
if(this.callbacks[name]){
this.callbacks[name].forEach(cb => cb(args))
}
}
}
// main.js
Vue.prototype.$bus = new Bus()
// child1
this.$bus.$on('foo', function() {})
// child2
this.$bus.$emit('foo')

 vuex

创建唯一的全局数据管理者store,通过它管理数据并通知组件状态变更。

$parent/$root

兄弟组件之间通信可通过共同祖辈搭桥,$parent或$root。

// brother1
this.$parent.$on('foo', handle)
// brother2
this.$parent.$emit('foo')

$children

父组件可以通过$children访问子组件实现父子通信。

// parent
this.$children[0].xx = 'xxx'

注意:$children不能保证子元素顺序

$attrs

包含了父作用域中不作为 prop 被识别 (且获取) 的特性绑定 ( class 和 style 除外)。当一个组件没有 声明任何 prop 时,这里会包含所有父作用域的绑定 ( class 和 style 除外),并且可以通过 vbind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。

// child:并未在props中声明foo
<p>{{$attrs.foo}}</p>
// parent
<HelloWorld foo="foo"/>

$listeners

在创建高级别的组件时非常有用,可以将回调函数写在父组件,子组件 v-on="$listeners"来调用

//父组件
<Brother2 @click="debugTit">
//子组件
<h5 v-on="$listeners">this is title(msg: $listeners)</h5>

 refs

获取子节点引用

// parent
<HelloWorld ref="hw"/>
mounted() {
this.$refs.hw.xx = 'xxx'
}

provide/inject

能够实现祖先和后代之间传值

// ancestor
provide() {
return {foo: 'foo'}
}
// descendant
inject: ['foo']

 

插槽

插槽语法是Vue 实现的内容分发 API,用于复合组件开发。该技术在通用组件库开发中有大量应用。

匿名插槽

// comp1
<div>
<slot></slot>
</div>
// parent
<comp>hello</comp>

具名插槽

将内容分发到子组件指定个位置

// comp2
<div>
<slot></slot>
<slot name="content"></slot>
</div>
// parent
<Comp2>
<!-- 默认插槽用default做参数 -->
<template v-slot:default>具名插槽</template>
<!-- 具名插槽用插槽名做参数 -->
<template v-slot:content>内容...</template>
</Comp2>

 

作用域插槽// comp3

<div>
<slot name="footer" :foo="foo"></slot>
</div>
// parent <Comp3> <!-- 把v-slot的值指定为作用域上下文对象 -->
<template v-slot:footer="slotProps"> 来自子组件数据:{{slotProps.foo}} </template> </Comp3>

footer -- 和具名插槽用法一样

slotProps -- 随便起名接收子组件数据

posted on 2021-06-24 10:28  京鸿一瞥  阅读(95)  评论(0)    收藏  举报