動態掛載Vue組件:函數式組件


提要

要動態掛載一個Vue組件Component,就必須實例化一個Vue對象,指定渲染函數和掛載位置。
而不能直接向document寫入html代碼的方式插入DOM,這不會觸發Vue框架的渲染。
和掛載App一樣:

import Vue from 'vue';
import App from './App.vue';

new Vue({
    render: h => h(App);
}).$mount('#app');

其中h是function (createElement, context)中的createElement。render其實應該這樣寫:

render: function (createElement, context) {
    return createElement(App);
}

將 h 作為 createElement 的別名是 Vue 生態系統中的一個通用慣例,實際上也是 JSX 所要求的。

文檔:https://cn.vuejs.org/v2/guide/render-function.html

函數式使用組件

以下文件實現了一個全屏的提示框組件,要彈出這個提示框,可以往頁面某個占位div上掛載:

new Vue({
    render: h => h(FrameAlert),
}).$mount($(document.body)[0])

等等,參數、事件怎么傳遞呢?

組件需要的一切都是通過 context 參數傳遞,那么如果我們傳遞給createElement的第一個參數是一個單文件導出的組件對象,
可以直接將 context 作為第二個參數,會成功到達該單文件組件的render函數!
context是一個包括如下字段的對象:

props:提供所有 prop 的對象
children: VNode 子節點的數組
slots: 一個函數,返回了包含所有插槽的對象
scopedSlots: (2.6.0+) 一個暴露傳入的作用域插槽的對象。也以函數形式暴露普通插槽。
data:傳遞給組件的整個數據對象,作為 createElement 的第二個參數傳入組件
parent:對父組件的引用
listeners: (2.3.0+) 一個包含了所有父組件為當前組件注冊的事件監聽器的對象。這是 data.on 的一個別名。
injections: (2.3.0+) 如果使用了 inject 選項,則該對象包含了應當被注入的屬性。

划重點!以下字段你很難在文檔中找到,但卻經常需要使用
on:事件
domProps:dom參數

所以,我們這樣傳遞參數和事件:

new Vue({
    render: h => h(FrameAlert, {
        props: { msg: '提示' },
        on: { click(event) { console.log(event.target.innerText); }, },
    }),
}).$mount($(document.body)[0])

文件:FrameAlert.vue

<template>
    <div class="frame_alert">
        <div class="alert">
            <div class="msg">
                <div>
                    <span v-html="filtedMsg"></span>
                </div>
            </div>
            <div class="buttons">
                <hr>
                <div class="btnwrapper">
                    <span @click=handle class="button" href="#">確定</span><span @click=handle class="button" href="#">取消</span>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
    export default {
        props: {
            msg: {
                type: String,
                default: "Message in here...",
            },
        },
        data() {
            return {
            };
        },
        computed: {
            filtedMsg() {
                return this.filteMsg(this.msg);
            },
        },
        methods: {
            handle(event) {
                this.$emit('click', event);
            },
            filteMsg(msg) {
                return msg.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/(?:\n|\\n)/g, '<br>');
            }
        },
        mounted() {
        },
    }
</script>

<style scoped>
    .frame_alert {
        position: fixed;
        top: 0;
        width: 100%;
        height: 100%;
        padding: 0;
        margin: 0;
        background: rgba(0, 0, 0, 0.8);
    }
    .alert {
        /* 外觀 */
        width: fit-content;
        min-width: 300px;
        max-width: 60%;
        border-radius: 15px;
        background: white;
        color: black;
        word-break: break-all;
        /* 定位 */
        position: absolute;
        top: 40%;
        left: 50%;
        transform: translate(-50%, -50%);
    }
    .msg {
        max-height: 200px;
        margin: 20px;
        margin-bottom: 80px;
        overflow: auto;
        text-align: center;
        font-size: 22px;
    }
    .msg::-webkit-scrollbar {
        /*隱藏滾輪*/
        display: none;
    }
    .buttons {
        position: fixed;
        margin: 0;
        bottom: 0;
        width: 100%;
        height: 60px;
        margin: auto;
        border-radius: 0 0 15px 15px;
    }
    .btnwrapper {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 80%;
        margin-top: 2px;
    }
    .button {
        text-align: center;
        font-size: 22px;
        display: inline-block;
        width: 50%;
        margin: 0;
        padding: 0;
        color: blue;
        text-decoration: none;
        cursor: pointer;
        user-select: none;
    }
    .button:active {
        text-shadow: 1px 1px 10px;
    }
</style>

END


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM