vue-cli
使用过vue的我想大家都知道,那么xxx.vue
组件是怎么运行的呢?怎么把template
,script
,style
渲染到页面上的呢?今天我们手动写了个简易的Vue组件在线编辑器玩一玩。
准备工作
- 安装
vuejs
- 新建
xxx.html
- 新建
xxx.css
编写页面
<div id="app">
<textarea name="" id="" cols="30" rows="30" v-model="content" autofocus placeholder="请输入vue模板"></textarea>
<div class="btn-center">
<button @click="run">运行代码</button>
<button @click="reset">清除</button>
</div>
</div>
<div id="result"></div>
<script src="./node_modules/vue/dist/vue.js"></script>
textarea
元素为vue
组件代码的编写部分,button
为按钮区域
textarea {
display: block;
width: 100%;
min-height: 100px;
max-height: 500px;
padding: 8px;
resize: auto;
}
button {
margin-top: 8px;
display: inline-block;
padding: 5px 16px;
font-size: 14px;
font-weight: 500;
line-height: 20px;
white-space: nowrap;
vertical-align: middle;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border: 1px solid;
border-radius: 6px;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
.btn-center{
text-align: center;
}
思路分解
在xxx.vue
中,我们写组件通常遵循一下模板
<template>
</template>
<script>
export default {
}
</script>
<style>
</style>
我们想到的是在拿到输入的内容之后,我们希望获取都tempalte
,script
,style
中的内容,然后通过Vue.extend( options )方法挂载到页面的元素上即可。
解析标签
我们需要拿到内容包括
<template> </template>
<script> </script>
<style> </style>
可以利用字符串的match
方法获取到每一段的开始标签的下标,开始标签的长度以及结束标签的下标,然后通过slice
方法截取获取到想要的内容。
getSource(type){
const reg = new RegExp(`<${type}[^>]*>`);
let content = this.content;
let matches = content.match(reg);
if(matches){
let start = content.indexOf(matches[0])+matches[0].length;
let end = content.lastIndexOf(`</${type}`);
return content.slice(start,end)
}
},
转化函数
在vue官网中,data
必须是一个函数,我们拿到的是一个字符串
export default {
data(){
return {
msg:'hello world'
}
},
methods:{
run(){
console.log("你好")
}
}
}
如何把一个字符串转化为可执行函数,可以参考如何让一个字符串执行?
我们可以用new Function
方法将字符串转化为可执行函数,我们需要的是
data(){
return {
msg:'hello world'
}
},
methods:{
run(){
console.log("你好")
}
}
利用字符串的replace
方法将export default
替换成return
得到
完成代码
run:function(){
let template = this.getSource("template");
if(!template) return
let script = this.getSource("script");
if(script){
script = script.replace(/export default/,"return");
}
let obj = new Function(script)();
obj.template = template;
let Profile = Vue.extend(obj);
new Profile().$mount("#result")
},
处理样式
通过正则解析拿到style
样式之后,添加到head
中即可
let styleCss = this.getSource("style");
let style = document.createElement("style");
style.innerHTML = styleCss;
document.head.appendChild(style);
总结
以上就是本文的全部内容了,只是简单地借助Vue.extend()
方法实现的一个简单的Vue组件在线编辑器
<div id="app">
<textarea name="" id="" cols="30" rows="30" v-model="content" autofocus placeholder="请输入vue模板"></textarea>
<div class="btn-center">
<button @click="run">运行代码</button>
<button @click="reset">清除</button>
</div>
</div>
<div id="result"></div>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
new Vue({
el: "#app",
data() {
return {
content: ""
}
},
methods: {
getSource(type) {
const reg = new RegExp(`<${type}[^>]*>`);
let content = this.content;
let matches = content.match(reg);
if (matches) {
let start = content.indexOf(matches[0]) + matches[0].length;
let end = content.lastIndexOf(`</${type}`);
console.log(content.slice(start, end));
return content.slice(start, end)
}
},
run: function () {
let template = this.getSource("template");
if (!template) return
let script = this.getSource("script");
if (script) {
script = script.replace(/export default/, "return");
}
let styleCss = this.getSource("style");
let style = document.createElement("style");
style.innerHTML = styleCss;
document.head.appendChild(style);
let obj = new Function(script)();
obj.template = template;
let Profile = Vue.extend(obj);
new Profile().$mount("#result")
},
reset() {
this.content = ''
}
}
})
</script>