原文链接: vue 实时显示组件源码
下一篇: 某职业技术学院形势与政策刷课脚本
左侧组件内容, 右侧组件源码
需要配合服务端
服务端代码查询接口
var express = require('express')
var app = express()
var bodyParser = require('body-parser');//解析,用req.body获取post参数
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
const fs = require('fs')
const cors = require('cors');
const path = require('path')
app.use(cors());
app.post('/getSource', function (req, res) {
console.log(req.body,typeof req.body)
let src = req.body.path
let filePath = path.join(process.cwd(),src)
console.log(filePath)
let source = fs.readFileSync(filePath, 'utf8')
res.json({source})
})
app.listen(3333, () => console.log('Example app listening on port 3000!'))
对应api
import axios from 'axios'
export const getSource = (path) => {
let url = "http://localhost:3333/getsource"
return axios.post(url,{
path
})
}
route中, 配合mixin, 在组件热更新时发送事件, 通知父组件刷新代码, 并将文件路径存入meta中
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import Login from './components/Login'
import MgrPage from './components/MgrPage'
Vue.use(Router)
const routes = [
{
path: '/',
name: 'home',
component: Home
},
{
path: '/Login',
component: Login
},
{
path: '/MgrPage',
component: MgrPage
},
{
path: '/about',
name: 'about',
component: () => import(/* webpackChunkName: "about" */ './views/About.vue')
},
{
path: '*',
redirect: '/home'
},
]
let mixin = {
mounted() {
console.log('mixin mounted')
},
beforeUpdate() {
console.log('mixin beforeUpdate')
this.update()
},
beforeMount() {
console.log('mixin beforeMount')
this.update()
},
methods: {
update() {
this.$emit('on-update')
}
}
}
const requireComponent = require.context('./components', true, /\.vue$/)
requireComponent.keys().forEach(
(filePath) => {
let componentName = requireComponent(filePath).default.name || ''
let component = requireComponent(filePath).default
console.log(componentName, component)
routes.push(
{
path: `/demo/${componentName}`,
component: {
...component,
mixins: [mixin]
},
meta: {
__file: component.__file
}
},
)
}
)
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes
})
vue.config 中设置暴露出 文件路径, 路径为 src/app.vue, 发送到服务端后进行路径拼接读取文件后返回
module.exports = {
// ...
chainWebpack: config => {
// ...
config.module
.rule('vue')
.use('vue-loader')
.loader('vue-loader')
.tap(options => {
options.exposeFilename = true
return options
})
}
};
app, 接受子组件刷新的事件, 并负责调用接口刷新代码
<template>
<div id="app">
<router-view
@on-update="refresh"
class="route-view-wrap"></router-view>
<codemirror
class="code-mirror-wrap"
v-model="code"
:options="cmOptions">
</codemirror>
</div>
</template>
<script>
import {getSource} from './api'
export default {
name: 'app',
components: {},
data() {
return {
list: [],
code: '',
cmOptions: {
tabSize: 4,
mode: 'text/javascript',
theme: 'material',
lineNumbers: true,
line: true,
}
}
},
methods: {
async refresh() {
console.log('refresh')
let resp = await getSource(this.$route.meta.__file)
console.log('source', resp)
this.code = resp.data.source
}
},
async mounted() {
console.log("mounted", this.$options)
console.log('==', this.$route.meta.__file)
this.refresh()
}
}
</script>
<style>
html, body {
margin: 0;
padding: 0;
}
#app {
height: 100vh;
width: 100vw;
display: flex;
/*background: deepskyblue;*/
box-sizing: border-box;
overflow: overlay;
/*overflow: auto;*/
flex-wrap: wrap;
}
.route-view-wrap {
width: 50%;
height: 100%;
}
.code-mirror-wrap {
width: 50%;
height: 100%;
border: 1px solid black;
}
</style>