如果要使用 vue3 runtime,也就是 vue.runtime.esm-browser.js,而不使用 vue.esm-browser.js。這兩個版本的差異是使用後者,有支援 template,可直接將 template 字串寫在 component 裡面,但如果使用 runtime library,因為這個檔案大小比較小,缺少了動態編譯 template 的功能,必須改寫為使用 render function。
實例
以下是可以直接在 browser 執行的範例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title></title>
</head>
<body>
<div id="app"></div>
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue@3.5.13/dist/vue.runtime.esm-browser.js",
"vue-i18n": "https://unpkg.com/vue-i18n@11.1.1/dist/vue-i18n.runtime.esm-browser.js"
}
}
</script>
<script type="module">
import { createApp, h } from 'vue';
import { createI18n, useI18n } from 'vue-i18n';
const messages = {
en: { greeting: 'Hello!' },
zh: { greeting: '你好!' }
};
const i18n = createI18n({
legacy: false,
locale: 'en',
messages
});
const App = {
setup() {
const { t, locale } = useI18n(); // 正確取得 t() 函數
const toggleLang = () => {
locale.value = locale.value === 'en' ? 'zh' : 'en';
};
return () =>
h('div', [
h('h1', t('greeting')),
h('button', { onClick: toggleLang }, '🌐 Switch Language')
]);
}
};
createApp(App).use(i18n).mount('#app');
</script>
</body>
</html>
compiler-dom
vue3 官方提供了一個 compiler-dom,可以將 template 字串轉換為 render function。
安裝首先要安裝 compiler-dom
npm i @vue/compiler-dom
撰寫一個 convert.js
// https://www.npmjs.com/package/@vue/compiler-dom
// npm i @vue/compiler-dom
const fs = require('fs');
const path = require('path');
const { compile } = require('@vue/compiler-dom');
const file = process.argv[2];
if (!file || !file.endsWith('.template.html')) {
console.error('請提供一個 .template html 檔案,例如:node convert.js MyComponent.html');
process.exit(1);
}
const filePath = path.resolve(process.cwd(), file);
const template = fs.readFileSync(filePath, 'utf-8');
// 編譯 template 成 render 函數
const { code } = compile(template, {
mode: 'module',
prefixIdentifiers: true, // 避免 with()
filename: file
});
// 產出 JS 檔案名稱
const baseName = path.basename(file, '.template.html');
const outputFile = `${baseName}.template.render.js`;
// // 包裝為可匯入的模組
const outputContent = `
${code}
`;
// 寫入檔案
fs.writeFileSync(outputFile, outputContent.trim());
console.log(`Render function 已輸出為:${outputFile}`);
使用方法
把 template 的部分,改為獨立的 test.template.html 檔案
<div>
<h1> {{ t("greeting") }} </h1>
<button @click="toggleLang()">🌐 Switch Language</button>
</div>
透過 nodejs 將 template 轉換為 render function
import { toDisplayString as _toDisplayString, createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"
export function render(_ctx, _cache) {
return (_openBlock(), _createElementBlock("div", null, [
_createElementVNode("h1", null, _toDisplayString(_ctx.$t("greeting")), 1 /* TEXT */),
_createElementVNode("button", {
onClick: $event => (_ctx.toggleLang())
}, "🌐 Switch Language", 8 /* PROPS */, ["onClick"])
]))
}
改寫原本的測試網頁
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title></title>
</head>
<body>
<div id="app"></div>
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue@3.5.13/dist/vue.runtime.esm-browser.js",
"vue-i18n": "https://unpkg.com/vue-i18n@11.1.1/dist/vue-i18n.runtime.esm-browser.js",
"render": "./test.template.render.js"
}
}
</script>
<script type="module">
import { createApp, h } from 'vue';
import { createI18n, useI18n } from 'vue-i18n';
import {render} from 'render';
const renderFn = render;
const i18n = createI18n({
legacy: false,
locale: 'en',
fallbackLocale: "en",
messageCompiler: null,
messages: {
"en": {
"greeting": 'Hello!'
},
"zh": {
"greeting": '你好!'
},
},
});
const App = {
setup() {
const { t, locale } = useI18n();
const toggleLang = () => {
locale.value = locale.value === 'en' ? 'zh' : 'en';
};
return {
t, locale, toggleLang
};
},
render: renderFn,
methods: {
}
};
createApp(App).use(i18n).mount('#app');
</script>
</body>
</html>
note
點擊切換語言時,網頁 console 會出現這樣的警告訊息
[intlify] the message that is resolve with key 'greeting' is not supported for jit compilation
不影響網頁操作,但還不知道為什麼會出現這個 warning
沒有留言:
張貼留言