有时候想在 Vue 单文件组件里试一试 Element UI 组件的用法,但每次都要启动运行环境,挺麻烦的,遂自己实现一个简易便捷的能在线写 Vue 单文件组件代码、使用 Element UI 组件、在线运行的网页。
为了方便使用,放到码上掘金了。
代码如下,一个 HTML 文件搞定,随处可用,核心就是利用 vue-template-compiler 解析 Vue 单文件组件代码。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Element UI Playground</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/element-ui/lib/theme-chalk/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/codemirror/lib/codemirror.css">
<style>
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
height: 100vh;
display: flex;
}
.code-area {
/* flex: 1; */
width: 50%;
resize: horizontal;
overflow: hidden;
flex-shrink: 0;
border-right: 1px solid #ccc;
}
.preview-area {
flex: 1;
overflow: auto;
}
#code {
display: none;
}
.run {
position: fixed;
top: 0;
right: calc(50% + 20px);
padding: 3px 10px;
color: #fff;
background-color: #5078ff;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
z-index: 2;
cursor: pointer;
}
.CodeMirror {
font-family: consolas;
font-size: 14px;
height: 100%;
}
</style>
</head>
<body>
<div class="code-area">
<textarea id="code"><template>
<div class="page">
<el-button @click="visible = true">Button</el-button>
<el-dialog :visible.sync="visible" title="Hello world">
<p>Try Element UI</p>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
visible: false
}
}
}
</script>
<style>
.page {
padding: 20px;
}
</style></textarea>
</div>
<span class="run" onclick="run()">运行</span>
<div id="app" class="preview-area"></div>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-template-compiler"></script>
<script src="https://cdn.jsdelivr.net/npm/element-ui/lib/index.js"></script>
<script src="https://cdn.jsdelivr.net/npm/codemirror/lib/codemirror.js"></script>
<script src="https://cdn.jsdelivr.net/npm/codemirror/addon/mode/overlay.js"></script>
<script src="https://cdn.jsdelivr.net/npm/codemirror/addon/edit/matchbrackets.js"></script>
<script src="https://cdn.jsdelivr.net/npm/codemirror/addon/edit/closebrackets.js"></script>
<script src="https://cdn.jsdelivr.net/npm/codemirror/addon/edit/closetag.js"></script>
<script src="https://cdn.jsdelivr.net/npm/codemirror/mode/xml/xml.js"></script>
<script src="https://cdn.jsdelivr.net/npm/codemirror/mode/javascript/javascript.js"></script>
<script src="https://cdn.jsdelivr.net/npm/codemirror/mode/css/css.js"></script>
<script src="https://cdn.jsdelivr.net/npm/codemirror/mode/htmlmixed/htmlmixed.js"></script>
<script src="https://cdn.jsdelivr.net/npm/codemirror/mode/vue/vue.js"></script>
<script>
const code = document.getElementById('code')
const app = document.getElementById('app')
const editor = CodeMirror.fromTextArea(code, {
lineNumbers: true,
matchBrackets: true,
autoCloseBrackets: true,
autoCloseTags: true,
mode: { name: 'vue' }
})
function run() {
const compiler = VueTemplateCompiler.parseComponent(editor.getValue())
const option = new Function(
compiler.script.content.replace('export default', 'return')
)()
option.template = compiler.template.content
const vueStyle = document.getElementById('vue-style')
if (vueStyle) document.getElementsByTagName('head')[0].removeChild(vueStyle)
if (compiler.styles[0]) {
const style = document.createElement('style')
style.id = 'vue-style'
style.innerHTML = compiler.styles[0].content
document.getElementsByTagName('head')[0].appendChild(style)
}
const component = new Vue(option).$mount()
app.innerHTML = ''
app.appendChild(component.$el)
}
</script>
</body>
</html>