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地址

相关推荐
YBN娜4 分钟前
Vue实现登录功能
前端·javascript·vue.js
阳光开朗大男孩 = ̄ω ̄=4 分钟前
CSS——选择器、PxCook软件、盒子模型
前端·javascript·css
minDuck9 分钟前
ruoyi-vue集成tianai-captcha验证码
java·前端·vue.js
小政爱学习!29 分钟前
封装axios、环境变量、api解耦、解决跨域、全局组件注入
开发语言·前端·javascript
魏大帅。35 分钟前
Axios 的 responseType 属性详解及 Blob 与 ArrayBuffer 解析
前端·javascript·ajax
花花鱼41 分钟前
vue3 基于element-plus进行的一个可拖动改变导航与内容区域大小的简单方法
前端·javascript·elementui
k093344 分钟前
sourceTree回滚版本到某次提交
开发语言·前端·javascript
EricWang13581 小时前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
September_ning1 小时前
React.lazy() 懒加载
前端·react.js·前端框架
晴天飛 雪1 小时前
React 守卫路由
前端框架·reactjs