闽公网安备 35020302035485号
<template>
<div>
<h1>{{ message }}</h1>
<button @click="changeMessage">改变消息</button>
</div>
</template>
<script>
export default {
data() {
return {
message: '初始消息'
};
},
methods: {
changeMessage() {
this.message = '消息已改变';
}
}
};
</script>
<style scoped>
h1 {
color: blue;
}
</style>
在上述代码中,<template> 定义组件 HTML 结构,含标题与按钮,用双花括号{{ }}数据绑定,按钮绑定点击事件。<script> 以export default导出包含数据message(用于模板显示)及方法changeMessage(改变message值)的对象。<style> 设定组件内 h1 标签文字颜色为蓝色。<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>堆代码 duidaima.com</title>
<style>
[data-v="component1"].test {
color: blue;
font-size: 24px;
}
[data-v="component2"].test {
color: red;
font-size: 20px;
}
</style>
</head>
<body>
<div data-v="component1" class="test">
<h1>这是组件1的标题</h1>
<p>这是组件1的一些内容描述。</p >
</div>
<div data-v="component2" class="test">
<h1>这是组件2的标题</h1>
<p>这是组件2的一些内容描述。</p >
</div>
</body>
</html>
加上作用域的样式,就只会作用于对应的作用域。如果是 vite 的话,使用的是 vIte 服务器( vite 启动后会在浏览器上启动一个服务器,用于模块的编译)里的 @vue/compiler-sfc。效果跟 vue2 的是一样的。具体也会在后面讲解。
// 读取.vue文件内容
function readVueFile(filePath) {
// 简单假设能读取到文件内容,实际需用Node.js文件系统API处理
return vueFileContent;
}
// 堆代码 duidaima.com
// 拆分.vue文件为template、script、style部分
function splitVueFile(vueFileContent) {
return [
vueFileContent.match(/<template>([\s\S]*?)<\/template>/)[1].trim(),
vueFileContent.match(/<script>([\s\S]*?)<\/script>/)[1].trim(),
vueFileContent
.match(/<style([\s\S]*?)>([\s\S]*?)<\/style>/)[2]
.trim(),
];
}
// 编译template为渲染函数
function compileTemplate(template) {
// <template>
// <div>
// <h1>{{ message }}</h1>
// <button @click="changeMessage">改变消息</button>
// </div>
// </template>
returnfunction render() {
// 经过一系列逻辑,处理成下面这样
return h("div", [
h("h1", this.message),
h(
"button",
{
on: {
click: this.changeMessage,
},
},
"改变消息"
),
]);
};
}
// 提取script内容作为模块(简化处理)
function extractScriptModule(script) {
return script;
}
// 处理style(简单处理scoped添加作用域,很简化)
function handleStyle(style) {
if (style.includes("scoped")) {
return style.replace(/([^\s,]+)/g, "$1[data-v-uniqueId]");
}
return style;
}
// 主函数模拟处理整个.vue文件
function processVueFile(filePath) {
const content = readVueFile(filePath);
const [template, script, style] = splitVueFile(content);
const renderFunction = compileTemplate(template);
const scriptModule = extractScriptModule(script);
const processedStyle = handleStyle(style);
return {
template: renderFunction,
script: scriptModule,
style: processedStyle,
};
}
// 示例调用
const result = processVueFile("example.vue");
1. 模板部分,就是被编译成渲染函数。<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue App without SFC</title> <link rel="stylesheet" href="styles.css"> </head> <body> <div id="app"></div> <script src="vue.js"></script> <script src="app.js"></script> </body> </html>在styles.css文件中定义样式:
h1 {
color: green;
}
在app.js文件中编写 Vue 应用的逻辑并实例化 Vue:var app = new Vue({
el: '#app',
data: {
message: 'Hello from non - SFC Vue'
},
methods: {
changeMessage() {
this.message = 'Message changed';
}
},
template: `
<div>
<h1>{{ message }}</h1>
<button @click="changeMessage">Change Message</button>
</div>
`
});
这种方式存在一些明显的弊端: