vue2组件封装--隔山打牛

隔山打牛

顾名思义,就是隔着一层组件,中间封装的组件不动, 只动最底层组件和引用的组件, 这样子就做到了解耦,还可以把底层的值抛到引用组件, 处理我们想要的事务, 从而实现了组件的封装

背景

这是我做 avue-form 二开时碰到的一个问题,中间的一个组件(avue-form), 是使用了 avue 中间的插件, 下面是avue-form预览组件的核心代码:

ini 复制代码
  <el-drawer title="预览"
             :visible.sync="previewVisible"
             size="60%"
             append-to-body
             :before-close="handleBeforeClose">
    <avue-form v-if="previewVisible"
               ref="form"
               class="afd-preview-form"
               :option="option"
               v-model="form"
               @submit="handlePreviewSubmit"></avue-form>
    <div class="afd-drawer-foot">
      <el-button size="medium"
                 type="primary"
                 @click="handlePreviewSubmit">确定</el-button>
      <el-button size="medium"
                 type="danger"
                 @click="handleBeforeClose">取消</el-button>
    </div>
  </el-drawer>

而我自定义的组件也是挂载在avue-form里面的, 属于最底层,我想要上抛事件, 但我又不想去扩展第三方的插件, 我该怎么办? 第一个我想到的, 用event-bus吧, 这个随意在组件里面穿梭都可以, 但通过以往的经验, 这个方法是下下策, 因为后期这样子的代码根本没法维护, 就像我很少用minxin和provide一样, 这些都是实在没办法了才用。我下载了第三方avue源码,试图能得到些启发。

vue 复制代码
  <component :is="getComponent(column.type,column.component)"
             v-model="text"
             v-bind="Object.assign(column,$uploadFun(column))"
             v-on="event"
             :column="Object.assign(column,params)"
             :dic="dic"
             :box-type="boxType"
             ref="temp"
             :disabled="column.disabled || disabled"
             :readonly="column.readonly || readonly"
             :placeholder="getPlaceholder(column)"
             :props="column.props || props"
             :propsHttp="column.propsHttp || propsHttp"
             :size="column.size || size"
             :table-data="tableData"
             :type="type || column.type"
             :column-slot="columnSlot"
             @keyup.enter.native="enterChange">
    <span v-if="params.html"
          v-html="params.html"></span>
    <template slot-scope="scope"
              v-for="item in getSlotName(column,'T',$scopedSlots)?[column]:[]">
      <slot :name="getSlotName(item,'T')"
            v-bind="scope"></slot>
    </template>
    <template v-for="item in columnSlot"
              slot-scope="scope"
              :slot="item">
      <slot v-bind="scope"
            :name="item"></slot>
    </template>
  </component>

看到这里,我有点恼火,咱平常封装组件时,中间组件不都是写v-on="$listeners"和v-bind="$attrs" 么, 这样子最外层组件可以直接绑定值,传到最里层,最里面事件也可以上抛到最外层,我试着在底层自定义组件抛事件,外头啥都接不到!!!但v-on="event"是啥玩意??

能看出门道或者,这么用过的童鞋可以就不用往下看了,嗯,这篇文章就是解释这个v-on="event"的,没明白的,那么接着往下看:

js 复制代码
computed: {
    event () {
      return this.column.event || {}
    }
    }

它是一个computed计算属性,还是一个对象??

搞个demo,深度剖析

后面,我弄了个简单demo,照猫画虎,还真让抛事件成功了!!!上demo:

这里我有三个组件,three是孙组件,贴三个组件的代码后面再讲解耦原理

这是App的

vue 复制代码
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld  :event='event' :msg="msg"/>
    <div>{{text}}</div>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
  name: 'App',
   data(){
    return {
     msg:'Welcome to Your Vue.js App',
     event:{
      agree:(val)=>{
        this.hello(val)
      }
     }
    }
  },
  methods:{
    hello(val){
      this.text=val
    }
  },
  components: {
    HelloWorld
  }
}
</script>

这是HelloWorld的

vue 复制代码
<template>
  <div class="hello">
    <h1 >{{ msg }}</h1>
   <three v-on='event' :msg='msg'></three>
  </div>
</template>

<script>
import three from './three.vue';
export default {
  name: 'HelloWorld',
  components:{
three  },
  props: {
    event:Object,
    msg: String
  },
    computed:{
   },
  methods:{
  }
}
</script>

这是three的

vue 复制代码
<template>
<button @click="click">dianji</button>
</template>

<script>
 export default {
   name:'ThreeSasdf',
 methods:{
  click(){
      this.$emit('agree','我是three的消息!')
    }
   }
 }
</script>

解析

这顿操作下来,我在app中真的把three中上抛的消息 '我是three的消息!' 给打印出来了!!也就是达到了,扩展组件three上抛事件,在app中定义

js 复制代码
` event:{
      agree:(val)=>{
        this.hello(val)
      },
      ....
     }`

这样子可以处理各种事务了,其中event是个对象,里面还可以继续定义其他很多的事件名,只要在孙组件中上抛了,那么祖组件event对应定义相应的名字接收,完美的略过了中间层helloword组件,达到了封装和解耦的目的!!其中需要注意的是,app中的this是指向app组件的,有兴趣的可以克隆该工程,地址如下:

如果各位感觉文字对你有帮助,请点击一个小小的赞,您的点赞是我继续创作的动力源泉!!

helloword git地址

相关推荐
hackeroink1 小时前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
迷雾漫步者3 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-3 小时前
验证码机制
前端·后端
燃先生._.4 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖5 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235245 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240256 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar6 小时前
纯前端实现更新检测
开发语言·前端·javascript
寻找沙漠的人7 小时前
前端知识补充—CSS
前端·css