preface

Breadcrumb navigation can record the page you have visited, which is convenient and quick to jump back to a page. This article introduces several ways to encapsulate breadcrumb components. Let’s take a look at how to implement it


Why do you need bread crumbs?

The concept of BreadcrumbNavigation comes from the fairy tale “hansel and gretel.” when hansel and gretel were walking through a forest, they got lost by accident. But they found that they had scattered bread crumbs everywhere along the way to help them find their way home.

After reading the above introduction, I believe you have understood the breadcrumb component usage scenario. That’s right, that’s right, it keeps track of which pages we clicked on so we can go back to a previous page.

By the time a page has been redirected multiple times, users may already be confused. As a program ape we may be through the address bar parameters can also be clearly defined in which position, after all, the web page is to be displayed to the user. Users to use, there is no breadcrumb navigation, may have a resistance to the web page, the use of breadcrumb navigation will each jump to the page down, can be a good solution to this problem.

Second, primary packaging

1. Implementation idea

  • Prepare the page structure and style needed to use the font icon inpublicIn the directoryindex.htmlTo introduce CDN font icon resources
    <link rel="stylesheet" href="//at.alicdn.com/t/font_2143783_iq6z4ey5vu.css">
    Copy the code
  • Define values that need to be passed in externally as custom attributes
  • Places the content written externally inside the tag in the default slot

2. Code demonstration

Create a bread-crumbs. Vue file in the SRC/Components directory. Use this directory to manage common components and customize the file names.

The code is as follows (example) :

<template>
  <div class='bread-crumbs'>
    <div class="bread-crumbs-item">
      <RouterLink to="/"> Home </RouterLink> </div> < I class="iconfont icon-angle-right"></i>

    <div v-if="parentName" class="bread-crumbs-item">
      <RouterLink v-if="parentPath" :to="parentPath">{{parentName}}</RouterLink>
      <span v-else>{{parentName}}</span>
    </div>

    <i v-if="parentName" class="iconfont icon-angle-right"></i>

    <div class="bread-crumbs-item">
      <span>
          <slot/>
      </span>
    </div>
  </div>
</template>

<script>
export default {
  name: 'BreadCrumbs',
  props: {
    parentName: {
      type: String,
      default: ' '
    },
    parentPath: {
      type: String,
      default: ' '
    }
  }
}
</script>

<style scoped lang='less'>
.bread-crumbs{
  display: flex;
  padding: 25px 10px;
  &-item {
    a {
      text-decoration: none;
      color: # 666;
      transition: all .4s;
      &:hover {
        color: #27ba9b;
      }
    }
  }
  i {
    font-size: 12px;
    font-style: normal;
    margin-left: 5px;
    margin-right: 5px;
    line-height: 22px;
  }
}
</style>
Copy the code

Create an index.js file in the SRC/Components directory to register the wrapped global components

import BreadCrumbs from './bread-crumbs'

export default {
  install (app) {
    app.component(BreadCrumbs.name, BreadCrumbs)
  }
}

Copy the code

Register as a plug-in in main.js

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
// Import and register
import myUI from './components'

createApp(App).use(store).use(router).use(myUI).mount('#app')

Copy the code

Use 3.

Passing in the common component requires the following value code (example) :

<template>
  <div class="home-banner">
    <bread-crumbs parentPath="/xxx" parentName="Electrical"> air conditioner </bread-crumbs> </div> </template> <script>export default {
  name: 'App'.setup() {
  }
}
</script>

Copy the code

Lack of 4.

It can only meet basic requirements and is unusable beyond level 2 navigation.

Three, advanced packaging

1. Implementation idea

  • referenceelementUIBread crumbsComponent code
<el-breadcrumb separator="/">
  <el-breadcrumb-item :to="{ path: '/' }">< /el-breadcrumb-item> <el-breadcrumb-item><a href="/"> Activity management </a></el-breadcrumb-item> <el-breadcrumb-item> <el-breadcrumb-item> Activity details </el-breadcrumb-item> </el-breadcrumb>Copy the code
  • Encapsulate each navigation as a component

2. Code demonstration

Continue to improve the code from the previous step of encapsulation

The code is as follows (example) : Create a bread-crumbs-item component in the SRC/Component directory with a customizable file name.

<template>
  <div class="bread-crumbs-item">
    <RouterLink v-if="to" :to="to"><slot /></RouterLink>
    <span v-else><slot /></span>
    <i class="iconfont icon-angle-right"></i>
  </div>
</template>
<script>
export default {
  name: 'BreadCurmbsItem',
  props: {
    to: {
      type: [String, Object]
    }
  }
}
</script>

Copy the code

Register as a global component in index.js in the SRC/Components directory

import BreadCrumbs from './bread-crumbs'
import BreadCrumbsItem from './bread-crumbs-item'

export default {
  install (app) {
    app.component(BreadCrumbs.name, BreadCrumbs)
    app.component(BreadCrumbsItem .name, BreadCrumbsItem )
  }
}
Copy the code

Modify the code in BreadCrumbs. Vue to place each item of navigation in the default slot

<template>
  <div class='bread-crumbs'>
    <slot />
  </div>
</template>

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

<style scoped lang='less'>
.bread-crumbs {
  display: flex;
  padding: 25px 10px;
  :deep(&-item) {
    a {
      text-decoration: none;
      color: # 666;The transition: all 0.4 s; &:hover { color:#27ba9b;
      }
    }
  }
  :deep(i) {
    font-style: normal;
    font-size: 12px;
    margin-left: 5px;
    margin-right: 5px;
    line-height: 22px;
  }
}
</style>

Copy the code

Use 3.

When used, use several BreadCrumbsItem code for the number of secondary navigations as follows (example) :

<template>
  <div class="home-banner"> <! --> <BreadCrumbs> <BreadCrumbsItem to="/"> </BreadCrumbsItem> <BreadCrumbsItem to="/xxx"</BreadCrumbsItem> </BreadCrumbsItem> air conditioning </BreadCrumbsItem> </BreadCrumbsItem> </BreadCrumbs> </div> </template> <script>export default {
  name: 'App'.setup() {
  }
}
</script>

Copy the code

Lack of 4.

There is an extra > indicator after the last navigation

Fourth, high order packaging

1. The train of thought

  • The ultimate version, using the Render function to create your own Mosaic.

CreateElement Render Render option with h function

  • Specify what the component displays:New Vue({options})
    • The EL option finds the container through a selector, and the contents of the container are the contents of the component
    • The template option,<div> Component contents </div>As component content
    • The render option, which is a function that returns the default createElement function (h), which creates the structure, and the render function returns the render as component content. It has a higher priority.

2. Code demonstration

Modify the code in the BreadCurmbsItem component

<template>
  <div class="bread-crumbs-item">
    <RouterLink v-if="to" :to="to"><slot /></RouterLink>
    <span v-else><slot /></span>
  </div>
</template>
<script>
export default {
  name: 'BreadCurmbsItem',
  props: {
    to: {
      type: [String, Object]
    }
  }
}
</script>

Copy the code

Modify the code in BreadCrumbs. Vue

Code examples (below) :

<script>
import { h } from 'vue'
export default {
  name: 'BreadCrumbs'.render() {// usage // 1. Template tag removal, single file component // 2. // 4. H first parameter tag name second parameter tag attribute object third parameter child node // requirement // 1. Create bread-crumbs parent container // 2. Remove the I tag of bread-crumbs-item because it is organized by the render function. The last item is not labeled with I. // 5. Render the dynamically created node const items = this in the bread- Crumbs tag.$slots.default()
    const dymanicItems = []
    items.forEach((item, i) => {
      dymanicItems.push(item)
      if (i < (items.length - 1)) {
        dymanicItems.push(h('i', { class: 'iconfont icon-angle-right'}}})))return h('div', { class: 'bread-crumbs' }, dymanicItems)
  }
}
</script>

<style lang='less'Bread-crumbs {display: flex; padding: 25px 10px; &-item { a { text-decoration: none; color:# 666;
      transition: all .4s;
      &:hover {
        color: #27ba9b;} } } i { font-size: 12px; margin-left: 5px; margin-right: 5px; line-height: 22px; // &:last-child {// display: none; // } } } </style>Copy the code

Use 3.

This approach, when encapsulated, makes global components more reusable and is highly recommended

<template>
  <div class="home-banner"> <! --> <BreadCrumbs> <BreadCrumbsItem to="/"> </BreadCrumbsItem> <BreadCrumbsItem to="/xxx"<BreadCrumbsItem > <BreadCrumbsItem to="/xxx/xx"> Air conditioner </BreadCrumbsItem> </BreadCrumbsItem> Remote control </BreadCrumbsItem> </BreadCrumbsItem> </BreadCrumbs> </div> </template> <script>export default {
  name: 'App'.setup() {
  }
}
</script>

Copy the code

As you can see, our self-packaged breadcrumb navigation now supports multi-level navigation. And the > indicator after the last navigation is gone.

5. Use JSX optimization

You can use JSX to rewrite the higher-order functional code, which is more concise and clear.

export default {
  name: 'BreadCrumbs',
  render () {
    // Vue2's render function takes h as its parameter
    // the h function in vue3 is imported
    // createElement(Tag name, tag attribute, tag child element)
    // console.dir(this.$slots.default())
    // Get all slots of the XtxBread component to fill with component instances
    const items = this.$slots.default()
    const results = []
    items.forEach((item, index) = > {
      results.push(item)
      // Manually generate an I icon and add it to the end of the breadcrumb project
      if (index < items.length - 1) {
        results.push(<i className='iconfont icon-angle-right'></i>)}})return <div className='bread-crumbs'>{results}</div>}}Copy the code

conclusion

Although the function is very small, but covers a lot of knowledge points, the above code has been tested in the local, you small partners can be directly used ~ feel useful, remember to click the likes collection oh