# Vite {%hackmd BJrTq20hE %} ## 安裝vite: - `npm init vite@latest` Or 直接指定项目名称和你想要使用的模板 `npm init vite@latest my-vue-app -- --template vue` Vite快速開發入門: https://www.gushiciku.cn/pl/gXvk/zh-hk ## 安裝配置Vue-Router: 1. `npm install vue-router@next --save` 2. 在src目錄下創建一個文件夾router/index.js,然後添加如下一些配置: //router首頁預設為 home.vue ```javascript= import { createRouter, createWebHashHistory } from 'vue-router'; const router = createRouter({ history: createWebHashHistory(), routes: [ { path: '/', component: () => import('../views/home.vue') } ] }); export default router ``` 3. 在main.js文件中引入Vue-Router: ```javascript= import router from './router'; createApp(App).use(router).mount("#app"); ``` 上面createApp(App)改成 ```javascript= const app = createApp(App) app.use(router) app.mount('#app') ``` ## 安裝scss編譯器: - `npm install -D sass` ## 檔案路徑別名設置(不像cli有 '@' or '~' 等符號): - [別名設置](https://ithelp.ithome.com.tw/articles/10270465?sc=hot),[環境變數設定](https://hackmd.io/@Jui-Cheng/Hk9fJ5bKi),[`process.cwd()` vs `__dirname` 有何不同](https://stackoverflow.com/questions/9874382/whats-the-difference-between-process-cwd-vs-dirname) > `process.cwd()`:傳回我們運行 node 時的目錄 `__dirname`:傳回目前運行檔案所在的目錄。 ```javascript= //vite.config.js import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' // 法一: const { resolve } = require('path'); // 法二: import { resolve } from 'node:path'; const rootPath = resolve(process.cwd()) // 返回目前工作目錄 const srcPath = resolve(__dirname, 'src') // 返回src目錄。 export default defineConfig({ base: './', plugins: [vue()], resolve: { alias: { '~': rootPath, '@': srcPath, '/images': 'src/assets/images', }, }, }) ``` 使用: &emsp;&emsp;`import Header from "/@/components/Header.vue";` &emsp;&emsp;`<img src='/images/xxx.png'/>` ## 動態圖片路徑問題: - 法一:https://vitejs.dev/guide/assets.html#importing-asset-as-url ```javascript= import imgUrl from './img.png' ``` - 法二:使用相對路徑 ```jsx= // 以下寫法皆可 image.src = '../assets/textures/door.jpg' image.src = '/assets/textures/door.jpg' ``` - 法三:https://vitejs.dev/guide/assets.html#new-url-url-import-meta-url e.g.: ```javascript= const url = new URL(url [, base]) const url = new URL('/foo', 'https://example.org/'); // https://example.org/foo ``` - url是一个表示绝对或相对 URL 的 DOMString。如果url 是相对 URL,则会将 base 用作基准 URL。如果 url 是绝对 URL,则无论参数base是否存在,都将被忽略。 - base 可选 是一个表示基准 URL 的 DOMString,在 url 是相对 URL 时,它才会起效。如果未指定,则默认为 ''。 > sample: ```javascript= const getImgSrc = (url) => new URL(`./assets/${url}`, import.meta.url).href; image.src = getImgSrc('door.jpg'); ``` - `import.meta.url`:返回当前模块的 URL 路径。 举例来说,当前模块主文件的路径是`https://foo.com/main.js`,`import.meta.url`就返回这个路径。如果模块里面还有一个数据文件`data.txt`,那么就可以用下面的代码,获取这个数据文件的路径。 `new URL('data.txt', import.meta.url)` ## github發布部屬 https://jerry-yeh.github.io/vue-3/20210911/13819/ - 環境設定檔(方式一) 透過 `process.env.NODE_ENV` 來判斷 Server 執行在開發或正式環境中 ```javascript= // vite.config.js import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import path from 'path'; // https://vitejs.dev/config/ export default defineConfig({ plugins: [vue()], build: { minify: true, }, resolve: { alias: { '@': path.resolve(__dirname, './src'), }, }, base: process.env.NODE_ENV === 'production' ? '/<REPO>/' : './', }); ``` `<REPO>`為github路徑 - 直接在npm指令設定(方式二) ```javascript= // package.json { "scripts": { "dev": "vite", "build": "vite build --base=/<REPO>/", "serve": "vite preview" }, } ``` ### gh-pages 套件 --- 1. `npm install --save gh-pages` 1. 設定 Github Page 的網址: ```json= // package.json { "name": "realtime-weather-app", "homepage": "https://myusername.github.io/my-app", // ... } ``` 1. 在script添加兩行指令: ```json= // package.json { "scripts": { "predeploy": "npm run build", "deploy": "gh-pages -d dist", // react為build // ... } } ``` 1. `npm run deploy` ### vite reactRouter 打包問題:[解法](https://blog.csdn.net/qq_24993119/article/details/124988629) - baseUrl設定只能影響非reactRouter路徑,因此router需另外設定 ```jsx= return ( <BrowserRouter basename={import.meta.env.BASE_URL}> <App /> </BrowserRouter> ); ``` 其他環境變量:[env-variables](https://cn.vitejs.dev/guide/env-and-mode.html#env-variables) - **`import.meta.env.MODE`**: {string} 应用运行的[模式](https://cn.vitejs.dev/guide/env-and-mode.html#modes)。 - **`import.meta.env.BASE_URL`**: {string} 部署应用时的基本 URL。他由[`base` 配置项](https://cn.vitejs.dev/config/shared-options.html#base)决定。 - **`import.meta.env.PROD`**: {boolean} 应用是否运行在生产环境。 - **`import.meta.env.DEV`**: {boolean} 应用是否运行在开发环境 (永远与 `import.meta.env.PROD`相反)。 - **`import.meta.env.SSR`**: {boolean} 应用是否运行在 [server](https://cn.vitejs.dev/guide/ssr.html#conditional-logic) 上。 ## 安裝element ui套件: &emsp;&emsp;`npm install element-plus --save` - 引入: ```javascript= import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' app.use(ElementPlus) ``` el-upload —手動上傳檔案,限制上傳檔案數量,檔案型別校驗等(手動設定) https://www.796t.com/article.php?id=250992 upload非空判斷: https://blog.csdn.net/weixin_43753330/article/details/95990910 ## vue3 報錯解決:找不到模組‘xxx.vue’或其相應的型別宣告。 https://iter01.com/528992.html - 報錯原因:typescript 只能理解 .ts 檔案,無法理解 .vue檔案 在預設`env.d.ts`加入設定 ```jsx= declare module '*.vue' { import { ComponentOptions } from 'vue' const componentOptions: ComponentOptions export default componentOptions } ``` ## unplugin-auto-import `npm i -D unplugin-auto-import` - 找不到模組 'unplugin-vue-components/vite' 或其對應的型別宣告。 需安裝:`npm i unplugin-vue-components -D` All:`npm i -D unplugin-auto-import unplugin-vue-components` ### 自動全域註冊組件 - 自動:[tutorial](https://blog.logrocket.com/how-to-automatically-import-register-vue-components/) ```jsx= // .\vite.config.ts import Components from 'unplugin-vue-components/vite' export default defineConfig( plugins: [ Components({ dirs: ["src/example/dir/here"] }) // 設定要自動引入的路徑 ] }) ``` - 手動:[turorial-舊](https://zerotomastery.io/blog/how-to-auto-register-components-for-vue-with-vite/),[turorial-新](https://blog.csdn.net/Chuinj/article/details/129789597) ## 使用 Jsx ### [Template vs JSX - 設定教學](https://zhuanlan.zhihu.com/p/586409247) JSX 优势: * template 则因为语法限制原因,不能够像 JSX 那样可以支持更动态的需求。 * JSX 相比于 template 还有一个优势,是可以在一个文件内返回多个组件 在实现业务需求的时候,优先使用 template,尽可能地利用 Vue 本身的性能优化。而对于动态性要求较高的组件可以使用 JSX 来实现。(比如用 JSX 来实现动态表单生成器) > 1. 安裝 `npm i -D @vitejs/plugin-vue-jsx` 2. 配置: ```jsx= // .\vite.config.js import vueJsx from "@vitejs/plugin-vue-jsx"; // 配置vue使用jsx export default defineConfig({ plugins: [vue(), vueJsx()], }); ``` 1. 使用: 注意:==script 中 lang 要改成 jsx==。也可以與`setup`同時使用 ```jsx= // render.vue <script lang="jsx"> import { ref } from "vue"; export default { setup() { const count = ref(100); return () => <div>count is: {count.value}</div>; }, }; </script> ``` ### 使用 jsx 教學: [《Vue3中使用JSX简明语法》](https://segmentfault.com/a/1190000042042220)、[使用 h 渲染 slot 範例](https://blog.csdn.net/leekuikui/article/details/126876400)、[jsx更詳細用法](https://segmentfault.com/a/1190000040712149) - sample code: 1. `props`:屬性裡的雙大括號 2. `slot`:元件中間的雙大括號,前面的 key 是 slot name ```jsx= render(row) { return ( <BaseTooltips label="刪除"> <n-popconfirm class="max-w-fit" positiveButtonProps={{ type: 'error' }} onPositiveClick={() => deleteItem()}> {{ trigger: () => ( <n-button circle tertiary type="error" size="large"> <n-icon size="25"><Trash /></n-icon> </n-button> ), default: () => ( '請確認是否刪除' ) }} </n-popconfirm> </BaseTooltips> </div> ) } ``` ### 指定單 row 置放按鈕 - 只有第一行有按鈕 ```jsx= render(row) { return (data.indexOf(row) == 0 ? <div class="flex gap-1"> <n-button type="primary" onClick={() => console.log(data.indexOf(row))}> Play </n-button> <n-button type="primary" onClick={() => play(row)}> bbb </n-button> </div> : '' ) } ``` ## vue3 自行製作組件 - [vue2、3屬性繼承](https://juejin.cn/post/7157195220038189087) 主要是在需繼承父層屬性的節點上加入`v-bind="$attrs"`即可,会接收属性和事件 ```jsx= <template> <n-tooltip placement="top" trigger="hover" v-bind="$attrs"> <template #trigger> <slot /> </template> <span>{{ label }}</span> </n-tooltip> </template> ``` - 延伸閱讀,[手把手创建Vue3组件库](https://segmentfault.com/a/1190000041592227) ## 動態載入路由、組件 - vue2 中,可以使用 webpack 自带的 require.context 批量引入模块 ```jsx= const modulesFiles = require.context('./modules', true, /\.js$/) ``` - 而在 vite 中使用`import.meta.glob`。[Glob導入-vite官網](https://cn.vitejs.dev/guide/features.html#glob-import)。 [導入組件用法](https://www.jb51.net/javascript/2917893dz.htm),[詳細說明(含webpack)](https://blog.csdn.net/guorui999/article/details/128814178)