vue远程加载sfc组件思路详解

2020-06-16 06:09:27易采站长站整理

const formatStyl = (sty, css, componentId) => {
let cssText = css
if (sty.scoped) {
cssText = css.replace(/[.w>s]+{/g, $1 => {
if (/>>>/.test($1)) return $1.replace(/s+>>>/, `[data-u-${componentId}]`)
return $1.replace(/s+{/g, $2 => `[data-u-${componentId}]${$2}`)
})
}
return cssText
}

$require 执行其中的的 JavaScript 代码,并返回值


const $require = (filepath, scriptContext) => {
const filename = path.resolve(__dirname, `../${filepath}`);
const module = { exports: {} }
let code = scriptContext ? scriptContext : fs.readFileSync(filename, 'utf-8')
let exports = module.exports
code = `(function($require,module,exports,__dirname,filename){$[code]})($require,module,exports,__dirname,filename)`
eval(code)
return module.exports
}

客户端请求组件并渲染

封装前端远程组件-remote.vue


<template>
<component :is="remote" v-bind="$attrs" v-on="$listeners"></component>
</template>
<script>
import Vue from "vue";
export default {
data() {
return {
remote: null
}
},
props: {
tagName: {
type: String,
defualt: "componentName"
}
},
created() {
fetch("http://localhost:3000/getComponent/"+this.tagName)
.then(res => res.json())
.then(sfc => {
let options = this.parseObj(sfc);
options.styles.forEach(css => this.appendSty(css));
this.remote = Vue.extend({
...options.script,
name: options.script.name || this.tagName,
template: options.template
});
});
},
methods: {
isObject(v) {
return Object.prototype.toString.call(v).includes("Object");
},
parseObj(data) {
if (Array.isArray(data)) return data.map(row => this.parseObj(row));
if (this.isObject(data)) {
let ret = {};
for (let k in data) {
ret[k] = this.parseObj(data[k]);
} return ret;
}
try {
let pattern = /function ([w]+)() { [native code] }/;
if (pattern.test(data)) {
return window[pattern.exec(data)[1]];
} else {
let evalData = eval(`(${data})`);
return typeof evalData == "function" ? evalData : data;
}
} catch (err) {
return data;
}
},
appendSty(css) { // 生成组件样式
let style = document.createElement("style");
style.setAttribute("type", "text/css");
var cssText = document.createTextNode(css);