首页 > 编程知识 正文

vue组件封装过程,vue组件封装优点

时间:2023-05-06 16:33:44 阅读:190196 作者:4749

1、封装组件的目的

封装业务逻辑相同、高度重复的代码,提高代码复用能力,减少代码冗余。

2、组件使用

(1)引用

importnavsfrom ' @/views/nav/index ' (2)注册

组件: { ' v-nav ' : navs } (3)使用

v-nav /v-nav 3、组件三要素

属性: props属性、inheritAttrs属性

事件:事件

插槽:插槽

(1)属性:

将数据从父组件传递到子组件的props属性

父母要加入孩子,需要props。 普通的props如下所示。

props : [‘data’,‘type’]

但是,通用组件的应用场景很复杂,需要向props传递的参数添加验证规则。 一般的格式如下。

props:{//基础型检查(null )意思是任何类型) propA: Number,//多种类型的propb3360(string, number )//必须传输,作为字符串的propc3360 ) type3360 required: true //必须传递},//数字中包含作为默认值的propd : { type : NUE/存在default: 100 //default缺省值,缺省值为100 } //数组/对象的缺省值为工厂函数中的propE: { type: Object,default 3360 fff //自定义验证函数propf : (validator : function ) value ) returnvalue10 ) http://www.Sina.com/

vue官方网站介绍了inheritAttrs的属性。 如果不希望组件的根元素继承特性,则可以在组件的选项中设置inheritAttrs: false。

让我们通过例子来验证一下。

父组件parent-component.vue

templatedivclass=' parent ' child-component AAA=' 1111 '/child-component/div/templatescriptimportchildcomponentfrast child-component ' export default { components : { child component }/script子组件

template div class='child '子组件/div/templatescriptexportdefault { inherit attrs 3360 true,mounted () } { console.log

元素

控制台

子组件child-component.vue设置inheritAttrs: false

template div class='child '子组件/div/templatescriptexportdefault { inherit attrs 3360 fasle,mounted () } { console.log

元素

控制台

总结:

从上面的示例可以看出,前提:父组件传递的属性没有注册在子组件的props中。

1 .如果设置为1.inheritattrs3360true (默认值),则从子组件的顶级标签元素(本示例中的div元素)中渲染从父组件传递的属性(本示例中的aaa=“1111”)

2 .如果设置为2.inheritattrs3360false,则在子组件的顶层标签元素(本示例中为div元素)中不会呈现从父组件传递的属性。 本例中的aaa=“1111”)。

3 .无论输入

heritAttrs为true或者false,子组件中都能通过$attrs属性获取到父组件中传递过来的属性。

(2)events:子组件触发父组件事件
在通用组件中,通常会需要有各种事件,比如复选框的 change 事件,或者组件中某个按钮的 click 事件,有时子组件需要触发一个事件,并传递给父组件。

// 子组件方法:触发父组件方法,并传递参数data到父组件handleSubmit(data){ this.$emit('submitToParent', data)} // 父组件调用子组件<child-component @submitToParent="parentSubmit"></child-component>... ...// 父组件中被触发的方法,接受到子组件传来的参数parentSubmit(data){ // 父组件的逻辑处理}

父组件中的逻辑要放在父组件处理,子组件基于父组件的数据做的逻辑放在子组件中处理; 这样既降低了耦合性,也保证了各自的数据不被污染

(3)留一个 slot
一个通用组件,往往不能够完美的适应所有应用场景 所以在封装组件的时候,只需要完成组件 80% 的功能,剩下的 20% 让父组件通过 solt 解决。
例如:
上面是一个通用组件,在某些场景中,右侧的按钮是 “处理” 和 “委托”。在另外的场景中,按钮需要换成 “查看” 或者 “删除” 在封装组件的时候,就不用写按钮,只需要在合适的位置留一个 slot,将按钮的位置留出来,然后在父组件写入按钮。

子组件<div class="child-btn"> <!-- 具名插槽 --> <slot name="button"></slot> <!-- 匿名插槽(每个组件只能有一个) --> <slot><slot></div> 父组件<child> <!-- 对应子组件中button的插槽 --> <button slot="button">slot按钮</button></child>

开发通用组件的时候,只要不是独立性很高的组件,建议都留一个 slot,即使还没想好用来干什么。

开发过程中,常常需要在子组件内添加新的内容,这时候可以在子组件内部留一个或者多个插口

(4)子组件改变父组件的数据
当我们把父元素的数据给子组件时,要传一个非基础类型,即传递对象or数组,子组件通过访问对象中的属性操作数据,因为对象和数组是传引用,所以在子组件中修改的时候,父组件也会同步改变,如下:

// 父组件要props传递给子组件的数据data:{ info:'父组件信息'} // 子组件 <template id="tpl"> <div> <button @click="change">change</button> <p>{{data.info}}</p> </div></template>... 省略部分无关代码 ...props:['data'],methods:{ change(){ this.data.info = 'change info' }}

当子组件点击change按钮改变数据的时候,父组件也会同步改变
(5)、vue组件封装v-model
首先来理解下 v-model

<input v-model="something"> <input v-bind:value="something" v-on:input="something = $event.target.value">

与组件一起使用时,简化为

<custom-input :value="something" @input="value => { something = value }"></custom-input>

所以对于一个组件来说v-model,它应该

1.接受value道具
2.用新值发出一个input事件

一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value 特性用于不同的目。model 选项可以用来避免这样的冲突:

<template> <input type="checkbox" v-bind:checked="checked" v-on:change="$emit('change', $event.target.checked)" ></template><script>export default { name: 'base-checkbox', model:{ prop: 'checked', event: 'change' }, props: {checked: Boolean}}

现在在这个组件上使用 v-model 的时候:

<base-checkbox v-model="lovingVue"></base-checkbox>

这里的 lovingVue 的值将会传入这个名为 checked 的 prop。同时当 触发一个 change 事件并附带一个新的值的时候,这个 lovingVue 的属性将会被更新。

我们来继续看嵌套组件时怎么再封装一个v-model,我们新建一个组件special-checkbox里面包含上面的组件base-checkbox,如何将子父组件的v-model打通

<template> <base-checkbox v-model="newlovingVue"></base-checkbox></template><script>export default { name: 'special-checkbox ', model:{ prop:'lovingVue',//要存在于proops event:'change'//当组件的值发生改变时要emit的事件名 }, props: ['lovingVue'], data:function(){ return{//要重新定义一个data,赋值为props中的值,因为组件时单数据流,不能直接修改props newlovingVue:this.lovingVue } }, watch:{//这里检测data中的值,一旦发生变化就提交事件到父组件 newlovingVue:function(newVal,oldVal){ this.$emit('change',newVal) } }}</script>

现在使用这个二次封装的组件的时候

<special-checkbox v-model="lovingVue"></base-checkbox>

(6)、子组件发射事件,父组件接收事件

自组件通过this.$emit(“inChange”,index)进行发射事件,inChange为事件名称,index为参数。

<template> <div class="child"> <v-switch v-model="item.in_switch" :label="item.in_switch? 'on':'off' " @change="inChange(index)"></v-switch> </div></template><script>export default { props:{ item: Object, index: Number }, methods:{ inChange(index){ // 父组件监听 inChange事件,将index传过去,将处理逻辑放在父组件 this.$emit("inChange",index); } }}</script>

父组件接收

<template> <div class="parent"> // 注意这里inChange的参数可有可无 <child :item="item" :index="index" @inChange="inChange" /> </div></template>import child from "../child";export default { components: { child }, data() { return { item: { in_switch: true, }, index: 0 } }, methods:{ // inchange事件处理,有index参数 inChange(index){ console.log( index) }, }}</script>

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。