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

相关推荐
Json_181790144801 小时前
电商拍立淘按图搜索API接口系列,文档说明参考
前端·数据库
风尚云网1 小时前
风尚云网前端学习:一个简易前端新手友好的HTML5页面布局与样式设计
前端·css·学习·html·html5·风尚云网
木子02041 小时前
前端VUE项目启动方式
前端·javascript·vue.js
GISer_Jing1 小时前
React核心功能详解(一)
前端·react.js·前端框架
捂月1 小时前
Spring Boot 深度解析:快速构建高效、现代化的 Web 应用程序
前端·spring boot·后端
深度混淆2 小时前
实用功能,觊觎(Edge)浏览器的内置截(长)图功能
前端·edge
Smartdaili China2 小时前
如何在 Microsoft Edge 中设置代理: 快速而简单的方法
前端·爬虫·安全·microsoft·edge·社交·动态住宅代理
秦老师Q2 小时前
「Chromeg谷歌浏览器/Edge浏览器」篡改猴Tempermongkey插件的安装与使用
前端·chrome·edge
滴水可藏海2 小时前
Chrome离线安装包下载
前端·chrome
m51272 小时前
LinuxC语言
java·服务器·前端