Vue常见组件封装(四)

一.菜单组件的封装

使用element-ui来掌握菜单组件的使用javascript

npm install element-ui

1.1 静态菜单

使用element-ui构建静态菜单css

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
<el-menu default-active="2" class="el-menu-vertical-demo">
    <el-submenu index="1">
        <template slot="title">导航一</template>
        <el-submenu index="1-1">
            <template slot="title">选项1-1</template>
            <el-menu-item index="1-1-1">选项1-1-1</el-menu-item>
            <el-menu-item index="1-1-2">选项1-1-2</el-menu-item>
        </el-submenu>
        <el-menu-item index="1-2">选项1-2</el-menu-item>
    </el-submenu>
    <el-menu-item index="2">
        导航二
    </el-menu-item>
    <el-menu-item index="3">
        导航三
    </el-menu-item>
    <el-menu-item index="4">
        导航四
    </el-menu-item>
</el-menu>

1.2 自定义菜单

<my-menu>
    <my-submenu>
        <template slot="title">导航1</template>
        <my-menu-item>选项1.1</my-menu-item>
        <my-menu-item>选项1.2</my-menu-item>
        <my-submenu>
            <template slot="title">导航1.3</template>
            <my-menu-item>选项1.3.1</my-menu-item>
            <my-menu-item>选项1.3.2</my-menu-item>
        </my-submenu>
    </my-submenu>
    <my-menu-item>导航2</my-menu-item>
    <my-menu-item>导航3</my-menu-item>
    <my-menu-item>导航4</my-menu-item>
</my-menu>

分别编写三个组件html

1.my-menuvue

<template>
    <ul><slot></slot></ul>
</template>

2.my-menu-itemjava

<template>
    <li><slot></slot></li>
</template>

3.my-submenunpm

<template>
    <div>
        <span @click="changeShow()"><slot name="title" ></slot></span>
        <ul v-if="isShow"><slot></slot></ul>
    </div>
</template>
<script>
export default {
    methods:{
        changeShow(){
            this.isShow = !this.isShow
        }
    },
    data(){
        return {isShow:true}
    }
}
</script>

1.3 组件的动态渲染

{
    menus: [
        {
            name: "选项1",
            children: [
                {
                    name: "选项1.1",
                    children: [{ name: "选项1.1.1" }, { name: "选项1.1.2" }]
                },
                { name: "选项2" }
            ]
        },
        { name: "选项2" },
        { name: "选项3" }
    ]
}

组件的封装element-ui

<my-menu>
    <template v-for="menu in menus">
        <my-menu-item :key="menu.name" v-if="!menu.children">{{menu.name}}</my-menu-item>
        <resub v-else :key="menu.name" :menu="menu"></resub>
    </template>
</my-menu>
<!-- 将重复的内容单独进行抽离 -->
<my-submenu >
    <template slot="title">{{menu.name}}</template>
    <template v-for="child in menu.children">
        <resub v-if="child.children" :menu="child" :key="child.name"></resub>
        <my-menu-item v-else :key="child.name">{{child.name}}</my-menu-item>
    </template>
</my-submenu>

二.Message组件

Message组件的调用方式数组

<template>
    <button @click="showMessage">点我啊</button>
</template>
<script>
export default {
    methods:{
        showMessage(){
            Message.info({ // 直接调用
                message:'hello 我帅不帅',
                duration:3000
            });
            this.$message.info({ // 经过实例调用
                message:'hello 你很帅',
                duration:3000
            });
        }
    }
}
</script>

2.1 编写Message组件

要考虑数据驱动视图,屡次点击显示多个弹层,给每一个层增长 id号,延迟时间和内容bash

<template>
    <div class="messages">
        <!-- 显示在数组中的层 -->
        <div v-for="message in messages" :key="message.id">
            {{message.message}}
        </div>
    </div>
</template>
<script>
export default {
    data(){
        return {messages:[]}
    },
    mounted(){
        // 给全部弹层增长惟一标示 方便弹层的卸载
        this.id = 0;
    },
    methods:{
        add(option){
            let id = this.id++; // id号
            let layer = {...option,id}
            this.messages.push(layer); // 将层存储起来
            layer.timer = setTimeout(()=>{
                this.remove(layer);
            },option.duration)
        },
        remove(layer){
            clearTimeout(layer.timer); // 清除定时器
            // 移除层 
            this.messages = this.messages.filter(message=>layer.id !== message.id);
        }
    }
}   
</script>

经过js文件控制显示Message弹层
步骤一:暴露调用方法app

// 暴露 不一样类型的弹层方法
const Message = {
  info(options){
      // 调用增长弹层方法
      getInstance(options).add(options);
  },
  warn(){},
  danger(){},
  success(){}
}
export {
  Message
}

步骤二:生产实例

import Vue from 'vue';
import MessageComponent from './Message.vue';
let getInstance = () =>{
    let vm = new Vue({
        render:h=>h(MessageComponent)
    }).$mount();
    let messageComponent = vm.$children[0];
    // 获取真实dom元素,将其挂在页面上
    document.body.appendChild(vm.$el);
    return {
        add(options){ // 调用组件的add方法
            messageComponent.add(options);
        }
    }
}
const Message = {
    info(options){
        // 调用增长弹层方法
        getInstance().add(options);
    },
    warn(){},
    danger(){},
    success(){}
}
// 暴露 不一样类型的弹层方法
export {
    Message
}

步骤三:实现单例

let instance;
let inst = () => {
    instance = instance || getInstance();
    return instance;
}
const Message = {
    info(options){
        // 调用增长弹层方法
        inst().add(options);
    },
    warn(){},
    danger(){},
    success(){}
}
// 暴露 不一样类型的弹层方法
export {
    Message
}

2.2 封装插件

install方法和use方法的应用

let _Vue;
export default {
    install(Vue,options){
        if(!_Vue){
            _Vue = Vue;
            let $message = {}
            Object.keys(Message).forEach(type => {
                $message[type] = Message[type]
            });
            Vue.prototype.$message = $message
        }
    }
}
// 组件中使用插件
import {Message} from './components/Message';
this.$message.info({
        content:'hello 你很帅',
        duration:3000
})
相关文章
相关标签/搜索