<template>
    <div :id="ctnId" :ref="ctnId" class="render-ctn">
        <span style="color: #9e9e9e;">暂无内容</span>
    </div>
</template>

<script>
import Vue from 'vue'

export default {
    name: 'VueRender',
    props: {
        options: {
            type: String,
            required: true
        }
    },
    data() {
        let id  =  parseInt(Math.random() * 10000000);
        let ctnId = "renderCtn" + id;
        let appId = "appId" + id;
        return {
            appId: appId,
            ctnId: ctnId,
            component: null,
            html: '',
            js: '',
            css: '',
            code: '',
        }
    },
    watch: {
        options: {
            handler(value) {
                this.removeRender();
                this.renderCode();
            },
            deep: true
        }
    },
    mounted() {
        this.removeRender();
        this.renderCode();
    },
    methods: {
        // 移除渲染内容
        removeRender() {
            // 移除元素
            let children = document.getElementById(this.ctnId).children;
            if (children == null) {
                return;
            }
            for (let i = children.length - 1; i >= 0; i--) {
                children[i].remove();
            }
            // 销毁组件
            if (this.component) {
                this.component.$destroy();
            }
        },
        // 渲染vue
        renderCode() {
            this.splitCode();

            if (this.html !== '' && this.js !== '') {
                const parseStrToFunc = new Function(this.js)();
                parseStrToFunc.template = this.html;
                const Component = Vue.extend(parseStrToFunc);
                this.component = new Component().$mount();
                this.$refs[this.ctnId].appendChild(this.component.$el);
            }
        },
        // 解析代码
        getSource(source, type) {
            const regex = new RegExp(`<${type}[^>]*>`);
            let openingTag = source.match(regex);

            if (!openingTag) return '';
            else openingTag = openingTag[0];

            return source.slice(source.indexOf(openingTag) + openingTag.length, source.lastIndexOf(`</${type}>`));
        },
        // 切割代码
        splitCode() {
            let code = this.options;
            const script = this.getSource(code, 'script').replace(/export default/, 'return ');
            const style = this.getSource(code, 'style');
            const template = `<div id="${this.appId}">${this.getSource(code, 'template')}</div>`;
            this.js = script;
            this.css = style;
            this.html = template;
        },
    }
}
</script>

<style scoped>
    .render-ctn {
        border: 1px dashed #1890ff;
    }
</style>
