VUE:mixin、slot的用法

vue 为我们提供了很多复用性的方式,slot 和 mixins 就是其中两种…下面对这两种方式做一下记录

开发中使用到了mixin混入与slot插槽。

mixin
vue中关于代码复用的一个实现方式,通过将多个组件的相同代码块提取出来放入到一个js文件中,再通过 mixins: [mixin]混入到组件内达到代码复用的目的,在项目具有多个相似功能的组件时很有用。

合并规则

钩子函数:同名钩子皆生效,且mixin会先于组件调用
数据对象:同名发生冲突时以组件内数据优先
值为对象的选项:methods、components、filters、directives,同数据合并方式。
( 这种规则方便于对mixin中不适用当前组件的代码进行灵活覆盖 )
插个眼:mixin在vue3中有了其替代品Composition API,其优点有


slot
创建组件时放置的一个占位,可在调用组件时自定义占位的具体显示内容,实现了复用组件的个性化的需求,在ui框架中应用广泛。

创建一个MyA.vue组件

匿名插槽

// MyA.vue:
<template>
    <a v-bind:href="url"  class="nav-link" >
          <slot></slot>
    </a>
</template>

// 使用组件:
<my-a>
    这里的内容会显示在<slot></slot>中
</my-a>

具名插槽

// MyA.vue:
<template>
    <a v-bind:href="url"  class="nav-link" >
          <slot name="slot1"></slot>
          <slot name="slot2"></slot>
          <slot></slot>
    </a>
</template>

// 使用组件:
<my-a>
    <template  v-slot:slot1> 这里的内容会显示在slot1中 </template>
    <template  v-slot:slot2> 这里的内容会显示在slot2中 </template>
    这里的内容仍然会显示在<slot></slot>中
    匿名插槽有一个default名字
    所以这样也行:
    <template  v-slot:default> 这里的内容会显示在slot中 </template>
</my-a>

作用域插槽

// MyA.vue:
// 组件使用时的作用域为父组件,不能直接使用组件内部的数据
<template>
    <a v-bind:href="url"  class="nav-link" >
      // 需在slot上绑定数据
      <slot v-bind:data="data">
        {{ data.value }}
      </slot>
    </a>
</template>

// 使用组件:
<my-a>
    <template  v-slot:default="receiveData"> 
        //这里使用
        {{ receiveData.data }}
    </template>
</my-a>
 

插槽使用场景

- 该组件被多个地方使用

- 每个父组件中对该组件的内部有一部分需要特殊定制

- slot可以让我们更好的复用组件的同时并对其定制化处理

- 可以理解为父组件想子组件传递了一段 html 文本

要求:

    1.子组件模板包含至少一个 插槽 <slot></slot>

    2.父组件整个内容片段将插入到 slot 所在的 DOM 位置,并替换掉 slot 标签本身

1.普通插槽 slot

父组件: 负责分发插槽内容

        <child ref=child>

            我是父组件分发给 child 的所有内容

        </child>

        父组件获取子组件可以通过 this.$refs.child 来做操作

 

子组件:  <template>

            <slot>这里可以放一些默认值</slot>

        </template>

        模板中放置一个 <slot></slot>组件,

        我们可以自定义组件中的方法和数据,封装一些通用逻辑,比如前几篇中封装的 scroll滚动组件

2.具名插槽 子组件通过 name 属性 来匹配父组件分发的内容

父组件: 添加 slot 属性来作为标识

        <div slot="header">我是 header 分发的内容 111</div>

        <div slot="main">我是 main 分发的内容222</div>

        <div slot="footer">我是 footer 分发的内容333</div>

 

      在2.6.0 以上使用的是 v-slot:header; 默认插槽为: v-slot:default

 

子组件: slot 添加 name 属性来接受父组件分发的 DOM 元素

        <template>

            <slot name="header"></slot>

            <slot name="main"></slot>

            <slot name="footer"></slot>

        </template>

    当然,我们还可以调换插槽的位置...

3.作用域插槽 父组件可以接收来自子组件的 slot 传递过来的参数值

可以理解为: 子组件中的作用域插槽可以为父组件中的插槽的展示提供数据

 

子组件:

    <template>

        <div>

            <slot name="header" :value="value"></slot>

        </div>

    </template>

    <script>

        export default {

            data() {

                return {

                    value: '我是子组件的值'

                }

            }

        }

    </script>

 

父组件:

    <child>

        <template slot="header" slot-scope="slotHeaderProps">

            渲染子组件传过来的对象中 value值{{ slotHeaderProps.value }}

        </template>

    </child>

 

    在 2.6 以上绑定值的方式: v-slot:header="slotHeaderProps"

    而且可以使用解构 v-slot:header="{value}", 将子组件传过来的值解构

 

    还有就是, 我们可以把 slot直接写在子组件行内, 不必另起一个 template

    即这样: <child v-slot:header="{value}">{{value}}</child>

vue3.0以后 slot 和 slot=”xxx”,slot-scope 的方式会被废弃…
新的用法slot, v-slot:xxx || v-slot:default, v-slot:xxx=”slotProps”

混入 Mixins 使用

- 也是为了实现代码逻辑复用

- 当多个组件中出现业务逻辑重复时我们就可以抽离重复代码片段,写成一个混入对象

- 父组件直接引入这个对象

代码演示

就拿一个比较常见的场景: 下拉加载更多数据; 这类业务在H5端可以说是非常常见了,当我们很多页面都要用到时,就可以抽离成一个混入对象

// 滚动加载

import {throttle} from "@/common/js/tool";

 

export const scrollMixin = {

  methods: {

    doScrollLoading() {

      // 滚动超出高度

      let scrollTop =

        window.pageYOffset ||

        document.documentElement.scrollTop ||

        document.body.scrollTop;

      // 滚动区域高度

      let scrollHeight =

        document.body.scrollHeight || document.body.scrollHeight;

      // 可视区高度

      let clientHeight =

        document.documentElement.clientHeight || document.body.clientHeight;

 

      if (scrollHeight - clientHeight - scrollTop <= this.bottomHeight) {

        // 组件中需加入开关和加载更多; 还是有些耦合了...

        if (!this.isLoadMore) {

          this.loadMore();

        }

      }

    }

  },

  computed: {

    bottomHeight() {

      return this.$store.state.footerHeight;

    }

  },

  mounted() {

    window.addEventListener("scroll", throttle(this.doScrollLoading, 100, 1));

  },

  destroyed() {

    window.removeEventListener("scroll", throttle(this.doScrollLoading, 100, 1));

  }

}

父组件中引入使用

import { scrollMixin } from "@/mixins/scrollMixin";

mixins: [scrollMixin]

 

注意组件中重写的方法会覆盖混入中的方法,loadMore和 isloadMore 需要在

引用的组件中进行重写

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值