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
})
相關文章
相關標籤/搜索