盘点从vue源码看到的冷门api__Vue.js
发布于 3 年前 作者 banyungong 1183 次浏览 来自 分享
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利

主题列表:juejin, github, smartblue, cyanosis, channing-cyan, fancy, hydrogen, condensed-night-purple, greenwillow, v-green, vue-pro, healer-readable, mk-cute, jzman, geek-black, awesome-green, qklhk-chocolate

贡献主题:https://github.com/xitu/juejin-markdown-themes

theme: vue-pro highlight:

vue冷门api

$listeners

官方解释:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。 通俗来讲其实就是将孙子组件的emit事件同时广播给了父组件在代码中使用场景即是vuex的场景,即需要将孙子组件的事件监听到爷爷组件, 这很有用,当组件只有很简单的功能时,不需要引入vuex这种重型框架。 以下为伪代码

父组件
<HelloWorld msg="Welcome to Your Vue.js App" @test1='test1' @test2='test2'/>
子组件
<div style="margin-bottom:400px;" @click="$emit('test1')">
      2223232
    </div>
    <v-scroll :onLoadMore="onLoadMore" :dataList="scrollData" v-on='$listeners'>
    </v-scroll>
 孙组件
     <div>
            <div class="nullData" v-show="dataList.noFlag" @click="$emit('test2')">测试</div>
    </div>

此时爷爷组件可以监听到孙组件和子组件的通讯方法,达到事件透传目的

$attrs

官方解释: 包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件——在创建高级别的组件时非常有用。

这个其实和上面的 $listeners 一样,爷爷组件想把自己的属性传递给孙子组件时,往往通过孙子组件 v-bind=’$attrs’ 此时就可以很好的接收爷爷组件给父组件传递所有属性。

爷爷组件

<template>
  <div id="app">
    <!--<img src="./assets/logo.png">-->
    <HelloWorld msg="Welcome to Your Vue.js App" :data='name' aaa='222' @test1='test1' @test2='test2'/>
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
// 爷爷组件
export default {
  name: 'app',
  data() {
    return {
      name: 'xiazhiyong'
    }
  },
  components: {
    HelloWorld
  },
  methods:{
    test2() {
      console.log('test2')
    },
    test1() {
      console.log('test1')

    }
  }
}
</script>

子组件

<template>
  <div>
    <div style="margin-bottom: 400px" @click="fn">2223232</div>
    <v-scroll
      v-on="$listeners"
      v-bind="$attrs"
    >
    </v-scroll>
  </div>
</template>
<style Lang="less">
</style>
<script>
import loadmore from "./scroll.vue";
export default {
  components: {
    "v-scroll": loadmore,
  },
  data() {
    return {
    };
  },
  methods: {

    fn() {
      console.log("tag", 111);
      this.$emit("test1");
    },
  },
};
</script>

孙子组件

<template >
  <div
    class="yo-scroll"
  >
    <div class="nullData" @click="test2">{{ $attrs }}</div>
  </div>
</template>
<script>
export default {
  data() {
    return {};
  },
  methods: {
    test2() {
      this.$emit("test2");
    },
  },
};
</script>

上面代码是代码的具体应用,其中也包含了$listeners的示例,在封装高阶组件时可以使用这两个属性。

inheritAttrs

默认情况下父作用域的不被认作 props 的 attribute 绑定 (attribute bindings) 将会“回退”且作为普通的 HTML attribute 应用在子组件的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。通过设置 inheritAttrs 到 false,这些默认行为将会被去掉。而通过 (同样是 2.4 新增的) 实例 property $attrs 可以让这些 attribute 生效,且可以通过 v-bind 显性的绑定到非根元素上。

上述配置主要是了防止父组件给子组件设置属性时,替换了子组件的相应属性。 根据以下代码示例进行分析吧。

父组件

<template>
  <div>
    <v-scroll
      v-on="$listeners"
      v-bind="$attrs"
      type='text'
    >
    </v-scroll>
  </div>
</template>
<style Lang="less">
</style>
<script>
import loadmore from "./scroll.vue";
export default {
  components: {
    "v-scroll": loadmore,
  },
};
</script>

子组件

<template >
<input type="number" v-model="text">
</template>
<script>
export default {
  data() {
    return {
        text: ''
    };
  },
  methods: {
  },
};
</script>

上面的由于父组件给子组件的根实例增加了type 此时input框的type属性会变为text类型,在一般情况下基本不会存在问题,而当父组件和子组件设置有冲突时,基本上会保留父组件的属性,设置这个参数为true之后便会消除影响。

provide / inject

以下为官方解释

这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。如果你熟悉 React,这与 React 的上下文特性很相似。

provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的 property。在该对象中你可以使用 ES2015 Symbols 作为 key,但是只在原生支持 Symbol 和 Reflect.ownKeys 的环境下可工作。

inject 选项应该是:一个字符串数组,或一个对象,对象的 key 是本地的绑定名,value 是:在可用的注入内容中搜索用的 key (字符串或 Symbol),或一个对象,该对象的:from property 在可用的注入内容中搜索用的 key (字符串或 Symbol)default property 是降级情况下使用的 value提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。

官方的解释优点云里雾里, 其实应该是由父组件提供一个对象或者实例,子孙组件通过一个inject 接收这个实例,或者对象来达到数据实例共享的目的,这个类似与react中provider的使用方法,通过一个中间人做相应的数据对象处理,达到高阶组件的目的。

element-ui select 组件的封装实例如下

	// select 根组件
    provide() {
      return {
        'select': this
      };
    },
    // select option组件
    inject: ['select'],
    // 此时我们即可以在这个实例中使用this.select操作根组件的方法,数据达到数据共享和实例传递目的

从这个组件里面我们可以得到启发, 假如我们需要封装动态表单时,可以将组件的注册表,传入到provider中,然后利用inject获取组件对象,此时我们通过传入component-map form—json(动态表单的配置)form-data 来实现一个动态表单。

版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者: 夏天是个胖子 原文链接:https://juejin.im/post/6915352530251677709

回到顶部