Vue2.6之——组件化

这是我第20篇简书。 1、组件通信 (1)父子通信 ① props-$emit ② $refs 短信验证码、图形验证码组件我经常用$refs this.$refs.captcha= 'xxx' ③ 子组件$children[0] 并不保证顺序,所以从来不用这个方法,除非只有一个子组件。 // parent this.$children[0].xx = 'xxx' (2)兄弟通信 通过共同的祖辈组件搭桥,$parent或$root。 $root 和 $parent 都能够实现访问父组件的属性和方法,两者的区别在于,如果存在多级子组件,通过$parent访问得到的是它最近的一级的父组件,通过$root得到的是它的根父组件。 brother1: this.$parent.$emit('foo'); brother2: this.$parent.$on('foo', handle) (3)祖先与后代通信 用于组件库的开发,只能祖先给后代传值.。 这时用props属性就会嵌套太多props,不是很合适。 祖先: provide() { return {hi: 'hello 后代'} } 后代:inject:['hi'] ----------------------------------- 可直接返回this,子组件直接拿祖先的数据: 祖先: provide() { return {hi: this} }, data() { return { grandfa:'dxl' } } 后代:

{{hi.grandfa}}

inject:['hi'] (4)任意两个组件之间通信:事件总线 或 vue 事件总线:创建一个Bus类负责事件派发、监听和回调管理 // Bus:事件派发、监听和回调管理 class Bus{ constructor(){ // { // eventName1:[fn1,fn2], // eventName2:[fn3,fn4], // } 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() 以上自定义bus类实现观察者模式 或者直接用vue实例即可。 Vue.prototype.$bus = new Vue() // child1 this.$bus.$on('foo', handle) // child2 this.$bus.$emit('foo') (5)$attrs和$listeners(基本被Vuex替代了) $listeners: 包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=”$listeners” 传入内部组件——在创建更高层次的组件时非常有用。 $attrs: 包含了父作用域中不被认为 (且不预期为) props 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 props 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind=”$attrs” 传入内部组件——在创建更高层次的组件时非常有用。 举例一: 想象一下,你打算封装一个自定义input组件——MyInput,需要从父组件传入type,placeholder,title等多个html元素的原生属性。此时你的MyInput组件props如下: props:['type','placeholder','title',...] 很繁琐不是吗?$attrs专门为了解决这种问题而诞生,这个属性允许你在使用自定义组件时更像是使用原生html元素。比如: // 父组件 // 子组件 让MyInput组件实现focus事件: // 父组件 // 子组件 举例二: 三个组件:Grandfa、Father、Son Grandfa => Son: (爷爷给孙子传值) 通过$attrs传值 // Grandfa 传了一个静态placeholder值: 请输入
{{value}}
// Father Vue.component("Wrapper",{ template:`
` }); // Son Vue.component("son",{ template:`
`, }); Son => Grandfa: (孙子通知爷爷) computed: { rewriteListener() { const vm = this; return Object.assign({}, this.$listeners, { input: (event) => vm.$emit("input", event.target.value) } ) } } 2、内容分发slot插槽 插槽语法是Vue实现的内容分发API,用于复合组件开发,在通用组件库开发中大量应用。 (注:Vue 2.6.0之后采用全新v-slot语法取代之前的slot、slot-scope) (1)匿名插槽 // comp1
// parent hello (2)具名插槽 // comp2
// parent (3)作用域插槽 以上两个子组件的插槽值只能由父组件决定安排,但是我们的实际业务中,往往是儿子安排老子...这时就要用到作用域插槽。 // comp3 // 子组件决定值是'your name is XXX'
// parent // slotProps这个命名可以随便起,或者直接解构: 3、sync修饰符 sync修饰符添加于v2.4,类似于v-model,它能⽤于修改传递到⼦组件的属性,可以简化子组件通知父元素更新传入参数这个动作的代码逻辑。 场景:⽗组件传递的属性⼦组件想修改 所以sync修饰符的控制能⼒都在⽗级,事件名称也相对固定update:xx。 // 父组件将value传给子组件并使用.sync修饰符。 // 子组件触发事件: this.$emit('update:obj1', "it is new key by my-com"); 4、实战1:自定义表单组件 做几个自定义组件来更好的巩固知识。 index.vue: KInput.vue: 重点:v-bind="$attrs 把父组件的 type="password"传了过来,但是此时会影响到div,这时就要用到 inheritAttrs,将其设为false避免顶层容器继承属性。 实现: 双向绑定::value 、@input 派发校验事件 elementUI form表单input部分源码: // 派发,就是子组件向父组件派发事件 dispatch (componentName, eventName, params) { // 获取当前组件的父组件 var parent = this.$parent || this.$root // 拿到父组件名称 var name = parent.$options.componentName // 通过循环的方式不断向父组件查找目标组件 while (parent && (!name || name !== componentName)) { parent = parent.$parent if (parent) { name = parent.$options.componentName } } // 当循环结束,证明目标父组件已找到(如果存在),就通知父组件触发相应事件 if (parent) { parent.$emit.apply(parent, [eventName].concat(params)) } }, KCheckBox.vue: 还可以通过设置model选项修改默认行为: KFormItem.vue: 实现: 给Input预留插槽 - slot 能够展示label和校验信息 能够进行校验 5、实战2:弹窗类组件 弹窗类组件的特点: 在当前vue实例之外独立存在,通常挂载与body 通过js动态创建,不需要在任何组件中声明 ----------- create.js:-------------- import Vue from 'vue' // 创建指定组件实例并挂载于body上 /** * Component 组件 * props 属性值 */ export default function create(Component, props) { // 0. 先创建vue实例 const vm = new Vue({ // render方法提供给我们一个h函数,它可以渲染VNode render(h) { return h(Component, {props}) } }).$mount(); // 更新操作 // 1. 上面vm帮我们创建组件实例 // 2. 通过$children获取该组件实例 cosole.log(vm.$root); const comp = vm.$children[0]; // 3.追加至body document.body.appendChild(vm.$el); // 4.清理函数 comp.remove = () => { document.body.removeChild(vm.$el); vm.$destroy(); } return comp; } ----------- notice.vue:-------------- 未完待续 。。。

本文章由javascript技术分享原创和收集

发表评论 (审核通过后显示评论):