封装一个高复用的面包屑组件,适用于多级场景

在封装面包屑组件发现,简单封装的面包屑组件的时候如果最后一个选项后不需要箭头,还需要单独进行样式更改,并且如果需要在中间的某一个选项需要进行特殊样式,则更加复杂,这种只适用于两级场景,多级场景下就不能使用。

因此选择封装一个高复用的面包屑组件,能适用于多级场景,用到了 render 选项和 h 函数。

参考element的面包屑组件,不需要对不同要求再进行专门设计,这正是我需要的。


通过bread和bread-item两个组件进行演示:(以下基于vue3.0,所有组件都定义为全局组件)

1.bread-item.vue

<template>
  <div class="bread-item">
    <RouterLink v-if="to" :to="to"><slot /></RouterLink>
    <span v-else><slot /></span>
  </div>
</template>

<script>
export default {
  name: 'BreadItem',
  props: {
    to: {
      type: [String, Object],
      default: ''
    }
  }
}
</script>

<style></style>

此处并不需要加入箭头,如果在此处加上则最后会多出一个不需要的箭头,将箭头在render中动态渲染就好了

2.bread.vue

<script>
import { h } from 'vue'
export default {
  name: 'Bread',
  render() {
    const items = this.$slots.default()
    const dymanicItems = []
    items.forEach((item, i) => {
      dymanicItems.push(item)
      if (i < items.length - 1) {
        dymanicItems.push(h('i', { class: 'arrow' }))
      }
    })
    return h('div', { class: 'bread' }, dymanicItems)
  }
}
</script>

<style lang="less">
.bread {
  display: flex;
  padding: 25px 10px;
  &-item {
    a {
      color: #666;
      transition: all 0.4s;
      &:hover {
        color: @xtxColor;
      }
    }
  }
  i {
    font-size: 12px;
    margin-left: 5px;
    margin-right: 5px;
    line-height: 22px;
  }
}
</style>

此处样式没有scoped,是为了里面的bread-item插槽也能使用 

index.vue

<template>
  <div class="top-category">
    <div class="container">
      <!-- 面包屑 -->
      <Bread>
        <BreadItem :to="{ path: '/' }">首页</BreadItem>
        <BreadItem to="/category">页面1</BreadItem>
        <BreadItem>页面2</BreadItem>
      </Bread>
    </div>
  </div>
</template>

<script>
export default {
  name: 'TopCategory'
}
</script>

<style></style>

最后在使用的时候就和element上的面包屑组件一样,需要跳转就加一个to


分析一下bread.vue中的代码

<script>
import { h } from 'vue'
export default {
  name: 'Bread',
  render() {
    const items = this.$slots.default()
    const dymanicItems = []
    items.forEach((item, i) => {
      dymanicItems.push(item)
      if (i < items.length - 1) {
        dymanicItems.push(h('i', { class: 'arrow' }))
      }
    })
    return h('div', { class: 'bread' }, dymanicItems)
  }
}
</script>

这里用到了creatElement函数和render选项

在Vue中指定组件显示的内容:new Vue({选项}),有三种方式

  • el 选项,通过一个选择器找到容器,容器内容就是组件内容
  • template 选项,<div>组件内容</div> 作为组件内容
  • render选项,它是一个函数,函数回默认传入createElement函数(h函数),这个函数用来创建结构,再render函数返回渲染为组件内容。它的优先级更高。

vue官方对render选项的解释是:字符串模板的代替方案,允许你发挥 JavaScript 最大的编程能力。该渲染函数接收一个 createElement 方法作为第一个参数用来创建 VNode。Vue 选项中的 render 函数若存在,则 Vue 构造函数不会从 template 选项或通过 el 选项指定的挂载元素中提取出的 HTML 模板编译渲染函数。

render函数的返回值就是html结构

在大多数情况下,我们可以使用模板创建HTML,但一些特殊情况下使用模板较为繁琐,可以使用渲染函数来解决

h函数有三个参数 1.节点名称 2.属性|数据 (对象) 3. 子节点,例如:h('div', { class: 'bread' }, "例子"),生成的就是 <div class="bread">例子</div>

在上述代码中,items是通过this.$slots.default()获取的所有插槽组成的数组,dymanicItems就是动态渲染的箭头图标

通过遍历items得到每一个插槽将其与箭头图标依次组合,并通过if判断去掉最后一个箭头,就完成了 首页>页面1>页面2 这样的结构

更多内容和例子可以参考vue官方文档

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mmsmd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值