1.封装Vue组件的一些技巧(5000)第一篇

1.封装Vue组件的一些技巧(5000)第一篇

Vue的组件系统

前言

全局组件组件设计的第一步是就是先要思考组件类型,(展示组件,业务组件,容器组件)考虑设计组件用例设计用例主要就是设计,组件的调用方式(组件,api)<button />  || this.$alert('xxxx')  考虑可能需要的属性   props  考虑事件(v-on)  子元素,需要接受的子元素  slot  方法扩展的方法,抛出的接口  可以供组件使用者调用的方法

Vue组件的API主要包含三部分:prop、event、slot

1.props 表示组件接收的参数,最好用对象的写法,这样可以针对每个属性设置类型、默认值或自定义校验属性的值,此外还可以通过type、validator等方式对输入进行验证2.slot可以给组件动态插入一些内容或组件,是实现高阶组件的重要途径;当需要多个插槽时,可以使用具名slot3.event是子组件向父组件传递消息的重要途径

单向数据流

单向数据流是Vue组件一个非常明显的特征,不应该在子组件中直接修改props的值如果传递的prop仅仅用作展示,不涉及修改,则在模板中直接使用即可如果需要对prop的值进行转化然后展示,则应该使用computed计算属性如果prop的值用作初始化,应该定义一个子组件的data属性并将prop作为其初始值在子组件修改props,却不会修改父组件,这是因为extractPropsFromVNodeData中是通过浅复制将attrs传递给props的。浅复制意味着在子组件中对对象和数组的props进行修改还是会影响父组件,这就违背了单向数据流的设计。因此需要避免这种情况出现。

组件之间的通信

组件通信就是两个或两个以上的组件数据进行传递,称为组件通信,而组件通信有这五种场景父子    props传递,    子组件通过$pa ren获取父组件实例拿到数据,推荐使用props子父    父组件使用子组件的数据    1,自定义事件,在子组中触发事件传递数据,父亲组件接受    2, $children获取子 组件实例    3, $refs 获取子组件实例兄弟    1.在兄弟1this.$parent.$emit(事件名,参数)    2.在兄弟2生命周期里面this.$parent.$on(事件名,事件处理函数)祖先和后代(跨级)    1.在祖先用provider来提供,    2.后代里面用inject接收属性名任意组件通信    1.在main.js里面vue.prototype.$bus=new vue()    2.发送this.$bus.$emit(事件名,参数)    3.created生命周期接收this.$bus.$on(事件名,事件处理函数)

“绕开”单向数据流

考虑下面场景:父组件将数据通过prop形式传递给子组件,子组件进行相关操作并修改数据,需要修改父组件的prop值(一个典型的例子是:购物车的商品数量counter组件)。根据组件单向数据流和和事件通信机制,需要由子组件通过事件通知父组件,并在父组件中修改原始的prop数据,完成状态的更新。在子组件中修改父组件的数据的场景在业务中也是比较常见的,用v-model可以解决

v-model

v-model本质上就是一个语法糖,实现原理其实就是上面说过的数据绑定加上底层的input事件监听,通过v-bind绑定一个数据传给子组件,子组件里面的model默认用value属性接受,然后子组件监听数据发生变化,emit触发父组件的input事件,通过触发事件来进行传值,实现了父子组件数据的双向绑定。

获得组件实例的引用

在开发组件中,获取组件实例是一个非常有用的方法。组件可以通过$refs、$parents、$children等方式获得vm实例引用$refs在组件(或者dom上)增加ref属性即可$parents获取子组件挂载的父组件节点$children,获取组件的所有子节点

表单验证组件

通常情况下,表单验证是表单提交前一个十分常见的应用场景。那么,如何把表单验证的功能封装在组件内部呢?下面是一个表单组件的示例,展示了通过获得组件的引用来实现表单验证功能。首先定义组件的使用方式,form接收model和rule两个propmodel表示表单绑定的数据对象,最后表单提交的就是这个对象rule表示验证规则策略,表单验证可以使用async-validator插件form-item接收的prop属性,对应form组件的model和rule的某个key值,根据该key从model上取表单数据,从rule上取验证规则<template><div class="page">    <form :model="form" :rule="rule" ref="baseForm">        <form-item label="姓名" prop="name">            <input v-model="form.name"/>        </form-item>        <form-item label="邮箱" prop="email">            <input v-model="form.email"/>        </form-item>        <form-item>            <button @click="submit">提交</button>        </form-item>    </form></div>
接下来让我们实现form-item组件,其主要作用是放置表单元素,及展示错误信息<template>    <label class="form-item">        <div class="form-item_label">{{label}}</div>        <div class="form-item_mn">            <slot></slot>        </div>        <div class="form-item_error" v-if="errorMsg">{{errorMsg}}</div>    </label></template><script>    export default {        name: "form-item",        props: {            label: String,            prop: String        },        data() {            return {                errorMsg: ""            }        },        methods: {            showError(msg) {                this.errorMsg = msg            }        }    }</script>通过FormItems获取每个form-item的引用,保存在formItems中暴露validate接口,内部调用AsyncValidator,并根据结果遍历formItems中每个表单元素的prop属性,处理对应的error信息        <template>    <div class="form">        <slot></slot>    </div></template><script>    import AsyncValidator from 'async-validator';    export default {        name: "form",        props: {            model: {                type: Object            },            rule: {                type: Object,                default: {}            }        },        data() {            return {                formItems: []            }        },        mounted() {            this.calcFormItems()        },        updated() {            this.calcFormItems()        },        methods: {            calcFormItems() {                // 获取form-item的引用                if (this.$slots.default) {                    let children = this.$slots.default.filter(vnode => {                        return vnode.tag &&                            vnode.componentOptions && vnode.componentOptions.Ctor.options.name === 'form-item'                    }).map(({componentInstance}) => componentInstance)                    if (!(children.length === this.formItems.length && children.every((pane, index) => pane === this.formItems[index]))) {                        this.formItems = children                    }                }            },            validate() {                let validator = new AsyncValidator(this.rule);                let isSuccess = true                let findErrorByProp = (errors, prop) => {                    return errors.find((error) => {                        return error.field === prop                    }) || ""                }                validator.validate(this.model, (errors, fields) => {                    this.formItems.forEach(formItem => {                        let prop = formItem.prop                        let error = findErrorByProp(errors || [], prop)                        if (error) {                            isSuccess = false                        }                        formItem.showError(error && error.message || "")                    })                });                return Promise.resolve(isSuccess)            }        }    }</script>到这里我们就完成了一个表单验证的组件

总结

文章整理了几种实现Vue组件的技巧以counter计数器组件为例子,展示了通过v-model语法糖父子组件的绑定以表单验证组件为例子,展示了通过获取子组件的实例来封装组件的方法关于封装组件库知识了解的还不是太深入,需要多多的学习和积累,才能让自己不断的进步,加油
免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部