奇怪的知识又增加了 (⊙_⊙)
。
使用原生 html 写 vue 项目。注意:是项目,而不是页面,此方式是不推荐的,毕竟有脚手架,但在一些及其特殊场景下,可能会需要类似的方式,因此作为一个记录。
这种方式唯一的优点就是写完可以直接扔服务器上了
很多人对 在 html 中运行 vue 项目这种内容,认知只停留在引入 vue 的 cdn 文件,然后在 html 里一顿写,就觉得 html 写 vue 不是很简单嘛,但请注意用词,是项目,而不是页面,你能写一个 .vue
页面引入让 html 去运行吗?显然不可以,而此文章就是说这个的。
正常想要在原生 html 中直接写 .vue
文件是不现实的,因为 html 压根就不认识 .vue 文件,只有脚手架才能识别,那如何才能让 html 识别 .vue
文件呢?其实也很简单,核心就是一个包 vue3-sfc-loader
因为 vue3-sfc-loader
可以直接解析 .vue
文件,所以可以使用在页面中远程加载 vue 组件的场景中
vue3-sfc-loader
在 cdnjs 上无法搜索到es 包支持 import 导入的写法,比如这样
<script type="module">
import { createApp, ref } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';
</script>
而 umd 包是直接运行在浏览器的,比如我引入了 vue.global.js
这就是一个 browser 包,我可以在 window 上访问到 Vue
实例
使用时就是这样
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const { createApp, ref } = Vue; // window.Vue
</script>
es 包是需要
script
标签添加type="module"
,导入方式为import
。而 umd 包引入之后,会自动挂载到 window 上,导入方式为解构const {...} = Vue
.vue
文件Live Server
插件打开,普通打开方式无法运行
这里统一用 es 文件,模仿脚手架结构进行搭建
vue
离线 es 文件: vue.esm-browser.prod.min.jsvue3-sfc-loader
离线 es 文件:vue3-sfc-loader.esm.jsindex.html
,并引入下载好的 vue 和 sfc 解析文件这种 Import maps
写法在 vue 官网上有 示例
特性: 其实就是一个路径映射,此时 import {} from "vue"
等价于 import {} from "./lib/es/vue.esm-browser.prod.min.js"
优点:
import {} from "vue"
。import {} from "./lib/es/vue.esm-browser.prod.min.js"
引入相对或绝对路径,冗余且意义不大<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<!-- vue 的挂载节点 -->
<div id="app"></div>
</body>
<script type="importmap">
{
"imports": {
"vue": "./lib/es/vue.esm-browser.prod.min.js",
"vue3-sfc-loader": "./lib/es/vue3-sfc-loader.esm.js"
}
}
</script>
<script type="module" src="./main.js"></script>
</html>
main.js
文件,写入 sfc 解析 vue 文件的规则,并挂载 vue 实例,由于 html 的 script 标签上写了 type="module"
,所以可以在 main.js
中使用 import
语法import { loadModule } from 'vue3-sfc-loader';
import * as Vue from 'vue';
const { defineAsyncComponent, createApp } = Vue;
const options = {
moduleCache: {
vue: Vue,
},
async getFile(url) {
const res = await fetch(url);
if (!res.ok) return;
return {
getContentData: (asBinary) => (asBinary ? res.arrayBuffer() : res.text()),
};
},
addStyle(textContent) {
const style = Object.assign(document.createElement('style'), {
textContent,
});
const ref = document.head.getElementsByTagName('style')[0] || null;
document.head.insertBefore(style, ref);
},
};
// 引入 App.vue 根文件
const loadComponent = defineAsyncComponent(() => loadModule('./pages/App.vue', options));
// 挂载 vue
createApp(loadComponent).mount('#app');
addStyle
是为了解析 .vue
文件中的 style
样式插入到 header 中。
App.vue
文件,写入测试内容,然后使用 Live Server
打开 html 文件<script setup>
import { ref } from 'vue';
const count = ref(0);
</script>
<template>
<h1>123</h1>
<div class="title">count: {{ count }}</div>
<button @click="count++">+1</button>
</template>
<style scoped>
.title {
color: red;
}
</style>
效果如图所示
这个需要对组件库有一定的熟悉程度,了解其构成结构,而且需要官方对 es 格式的组件库文件有相当完善的支持。目前测试下来,只有 antd vue
对此方式的支持度最完善,可以在 cdnjs 中搜索下载。 element plus
arco vue
这些组件库对 es 的支持度并不是特别好,如果想要使用,只能退而求其次,使用 umd 格式,这种方式就不能 import 导入,而是从 window 上获取使用。
antd vue
相关的 min.js 和 css 并在 index.html
使用 map 映射(官网上还明确标注依赖了 dayjs 的 plugin 插件)<link rel="stylesheet" href="./lib/es/antd.reset.min.css" />
<script type="importmap">
{
"imports": {
// ...
"antd": "./lib/es/antd.esm.min.js"
}
}
</script>
main.js
中注册组件库import * as antd from 'antd';
const options = {
moduleCache: {
vue: Vue,
antd: antd, // 组件库等第三方包不在 use 注册,在此处注册,否则 sfc 会将 antd 识别为项目内部的 vue 组件,找不到而报错
},
// ...
};
<script setup>
import { ref } from 'vue';
import { Button } from 'antd';
const count = ref(0);
</script>
<template>
<span class="title">count: {{ count }}</span>
<button @click="count++">+1</button>
</template>
至此,离线方式搭建 vue 项目就此完成。
其实这种方式的缺点还是蛮多的,如果想用的组件库 es 支持度不够或有问题,只能选择 umd 格式使用