VueJS自定义组件之弹窗组件和树形组件

弹窗组件

这类组件的特点是在当前Vue实例之外存在,通常挂载与body,上在使用element-ui弹窗组件的时候,我们可以看到这一点:
VueJS自定义组件之弹窗组件和树形组件_第1张图片
并且它们是通过JS动态创建的,不需要在任何组件中声明。接下来我们看具体代码实现。

create.js

创建一个js文件,用来创建弹窗实例

import Vue from 'vue'
export default function create (comp, props) {
  const app = new Vue({
    render (h) {
      return h(comp, { props })
    }
  }).$mount()
  // app.$el为该虚拟DOM的真实DOM
  document.body.appendChild(app.$el)
  // 销毁
  const com = app.$children[0]
  com.remove = function () {
    document.body.removeChild(app.$el)
    app.$destroy()
  }
  return com
}

默认导出一个创建弹窗组件实例的方法,入参1为需要展示的弹窗组件,入参2为该组件的配置对象。首先通过render函数将组件转换成vNode,由于不能通过$mount将组件直接挂载到body上,所以需要我们手动挂载,document.body.appendChild(app.$el),并且为该组件实例添加移除销毁的方法,避免内存泄漏。

模板转换成浏览器认识的HTML过程,
1、template->AST render(compile解析template)
2、AST render->vNode (render函数方法运行)
3、VNode->DOM (vDom.patch)

KNotice.vue

需要展示的弹窗组件

<template>
  <div class="notice" v-if="isShow">
    <h3>{{ title }}</h3>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  props: {
    title: { type: String },
    message: { type: String },
    duration: { type: Number, default: 2000 }
  },
  data () {
    return {
      isShow: false
    }
  },
  methods: {
    show () {
      this.isShow = true
      setTimeout(() => {
        this.hide()
      }, this.duration)
    },
    hide () {
      this.isShow = false
      this.remove()
    }
  }
}
</script>

<style lang="scss">
.notice {
  position: absolute;
  top: 20px;
  right: 0;
  left: 0;
  margin: auto;
  width: 300px;
  height: 300px;
  background: #ff00ff;
}
</style>

App.vue

使用弹窗组件

<template>
  <div id="app">
    <button @click="clickHandle">click</button>
</template>

<script>
import create from './utils/create'
import KNotice from './components/notice/KNotice'
export default {
  name: 'App',
  methods: {
    clickHandle () {
      const notice = create(KNotice, {
        title: 'title',
        message: 'this is mesage',
        duration: 1000
      })
      notice.show()
    },
  }
}
</script>

<style lang="scss"></style>

效果图

VueJS自定义组件之弹窗组件和树形组件_第2张图片

树形组件

树形组件是典型的递归组件,像element-ui中的菜单组件都是这一类组件的实现

tree.vue

<template>
  <div>
    <li>
      <p @click="toggle">
        {{ model.title }}
        <span v-if="isFolder">[{{ open ? "-" : "+" }}]</span>
      </p>
      <ul v-show="open" v-if="isFolder">
        <item v-for="(item,index) in model.children" :key="index" :model="item"> </item>
      </ul>
    </li>
  </div>
</template>

<script>
export default {
  name: 'item',
  props: {
    model: {
      type: Object
    }
  },
  data () {
    return {
      open: false
    }
  },
  computed: {
    isFolder () {
      return this.model.children && this.model.children.length
    }
  },
  methods: {
    toggle () {
      if (this.isFolder) {
        this.open = !this.open
      }
    }
  }
}
</script>

<style lang="scss" scoped></style>

App.vue

<template>
  <div id="app">
    <ul>
      <item :model="model"></item>
    </ul>
  </div>
</template>

<script>
import Item from './components/tree'
export default {
  name: 'App',
  components: {
    Item
  },
  data () {
    return {
      list: {
        id: 1,
        title: '递归组件1',
        children: [
          {
            id: 2,
            title: '递归组件2',
            children: [
              {
                id: 4,
                title: '递归组件4'
              },
              {
                id: 5,
                title: '递归组件5'
              }
            ]
          },
          {
            id: 3,
            title: '递归组件3'
          }
        ]
      },
      model: {
        title: 'a',
        children: [
          {
            title: 'b'
          },
          {
            title: 'c',
            children: [
              {
                title: 'cc'
              },
              {
                title: 'dd'
              }
            ]
          }
        ]
      }
    }
  },
 }
</script>

<style lang="scss"></style>

VueJS自定义组件之弹窗组件和树形组件_第3张图片

你可能感兴趣的:(VueJS)