vue 异步加载远程组件(支持编译less语法)

本代码已组件化,可以直接使用。

说明:本组件可以直接解析.vue文件,为了支持less语法解析,在组件中引入less.js,可在less官网下载。

组件代码

<template>
    <div class="remote">
        <component :is="currentView" v-bind="$props"/> 
    </div>
</template>
<script>
import Axios from 'axios';
import '@/utils/less.min';


export default {
    props:{
        url:{
            type:String,
            default(){
                return null;
            }
        }
    },
    data(){
        return {
            resData:null,
            cssId:null,
        }
    },
    computed:{
        currentView(){
            if(!this.resData)return {template:"<div class='remoteInfo'>正在加载中。。。</div>"};
            const tplData = this.resolveStr(this.resData);
            let ponentObj = new Function(`return ${tplData.sctipts.slice(tplData.sctipts.indexOf('{'),tplData.sctipts.lastIndexOf('}')+1)}`)();
            ponentObj.template = tplData.templates;
            this.$el.setAttribute('class',`remote css${this.cssId}`);
            if(!document.querySelector(`style[id=css${this.cssId}]`)){//防止重复创建
                let cssStr = `
                    .css${this.cssId}{
                        ${tplData.styles}
                    }
                `;
                this.resolveCss(cssStr);
            }
            return ponentObj;
        }
    },
    watch:{
        url(){
            this.getData();
        }
    },
    mounted(){
        this.getData();
    },
    methods:{
        getId() {
            var d = new Date().getTime();
            var uid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                var r = (d + Math.random()*16)%16 | 0;
                d = Math.floor(d/16);
                return (c=='x' ? r : (r&0x3|0x8)).toString(16);
                });
            return uid;
        },
        resolveCss(lessInput){
            less.render(lessInput).then(function(output) {
                let style = document.createElement("style");
                style.setAttribute("type", "text/css");
                style.setAttribute("id",'css' + this.cssId);
                if(style.styleSheet)// IE
                    style.styleSheet.cssText = output.css;
                else {// w3c
                    var cssText = document.createTextNode(output.css);
                    style.appendChild(cssText);
                }
                var heads = document.getElementsByTagName("head");
                if(heads.length)
                    heads[0].appendChild(style);
                else
                    document.documentElement.appendChild(style);
            }.bind(this));
        },
        resolveStr(str){
            return {
                templates:str.match(/<template>([\s\S]*)<\/template>/)[1],
                sctipts:str.match(/<script.*>([\s\S]*)<\/script>/)[1],
                styles:str.match(/<style.*>([\s\S]*)<\/style>/)[1],
            }
        },
        async getData(){
            let remoteData = this.$store.getters.getRemoteByUrl(this.url);
            if(remoteData){
                this.resData = remoteData.resData;
                this.cssId = remoteData.cssId;
            }else{
                const res = await Axios.get(this.$props.url);
                this.cssId = this.getId();
                this.resData = res.data;
                this.$store.dispatch('doAction',{
                    event:'addRemote',
                    data:{url:this.url,cssId:this.cssId,resData:this.resData}
                });
            }        
        }
    }
}
</script>

 

posted @ 2018-10-26 19:21  时间脱臼  阅读(3476)  评论(0编辑  收藏  举报