Vue $listeners和$attrs组件库二次封装利器

2,875 阅读2分钟

$listeners和$attrs

这个东西说白了就是为了父子组件深层嵌套的方便传值 具体的:juejin.cn/post/684490…

再看不懂emmm...去官网看介绍(cn.vuejs.org/v2/api/#vm-…)

选个组件库(Vant为例)

官网

youzan.github.io/vant/#/zh-C…

安装

# 通过 npm 安装
npm i vant -S

# 通过 yarn 安装
yarn add vant

引用

//全局引入
import Vant from 'vant'
Vue.use(Vant)

//按需自己去官网

选择一个需要封装的组件(van-list为例)

新建一个vue文件,来最van-list的组件进行封装

<!--test-list.vue-->
<template>
    <van-list   v-on="$listeners" :offset="1" v-bind="$attrs">
      <slot></slot>
    </van-list>
</template>
<script>
export default {
  
};
</script>

在建一个调用此封装组件的vue文件

<!--listeners-attrs.vue-->
<template>
    <test-list v-model='loading' :finished='finished' loading-text="正在加载"></test-list>
</template>
<script>
import TestList from "./test"
export default {
    components:{TestList},
    data:function(){
        return {
            finished:false,
            loading:false
        }
    }
};
</script>

以这种方式,可以对第三方的组件库进行二次封装,无需额外的子父传值(v-model是个特殊)

van-list的v-model的特殊

van-list的v-model在所封装的组件直接使用时,即<test-list ==v-model='loading'== :finished='finished' loading-text="正在加载">会出现组件共能失效,如果给loading赋值是没有效果的,导致整个组件功能失效,出现失效的情况,我们就尽量把这个属性放到原组件中,通过其它方式传给父组件

* 第一种方案
<!--test-list.vue-->
<template>
    <van-list  v-model='loading'  v-on="$listeners" :offset="1" v-bind="$attrs">
      <slot></slot>
    </van-list>
</template>
<script>
export default {
  props:{
    value:{
      type:Boolean
    }
  },
  model:{
      prop:'value',
      event:'changeValue'
  },
  computed:{
      loading:{
          get(){
              return this.value
          },
          set(val){
              this.$emit('changeValue',val)
          }
      }
  }
};
</script>
<!--listeners-attrs.vue代码不变-->
* 第二种方案
<!--test-list.vue-->
<template>
    <van-list  v-model="value"  v-on="$listeners" :offset="1" v-bind="$attrs" finished-text="--没有更多了--">
      <slot></slot>
    </van-list>
</template>
<script>
export default {
  data:function(){
    return {
      value:false
    }
  },
  props:{
    loading:{
      type:Boolean
    }
  },
  watch:{
    loading:function(val){
      this.value=val
    }
  }
};
</script>
<!--listeners-attrs.vue-->
<template>
    <test-list :loading='loading' :finished='finished' loading-text="正在加载"></test-list>
</template>
<script>
import TestList from "./test"
export default {
    components:{TestList},
    data:function(){
        return {
            finished:false,
            loading:false
        }
    }
};
</script>