Skip to content

Instantly share code, notes, and snippets.

@flashlin
Last active June 16, 2021 00:06
Show Gist options
  • Save flashlin/225bcafdc1efe0bcf64374a3163fbc5a to your computer and use it in GitHub Desktop.
Save flashlin/225bcafdc1efe0bcf64374a3163fbc5a to your computer and use it in GitHub Desktop.
[upgrade to vue 3, vite tsx 2021-05-22] #vue3
{
"tabWidth": 3,
"useTabs": false,
"singleQuote": true,
"semi": false,
"trailingComma": "none"
}
2021-05-22
Vue CLI 的包名稱由 vue-cli 改成了 @vue/cli
如果你已經全局安裝了舊版本的 vue-cli(1.x或2.x)
你需要先通過 npm uninstall vue-cli -g 或 yarn global remove vue-cli 卸載它
可以使用下列任一命令安裝這個新的包:
npm install -g @vue/cli
# OR
yarn global add @vue/cli
vue create sample
下面是建立 vue project + vite 步驟
yarn create @vitejs/app sample --template vue
yarn add eslint -D
生成eslint配置
node_modules/.bin/eslint --init
Q: How would you like to use ESLint?
To check syntax only
To check syntax and find problems
To check syntax, find problems, and enforce code style 選擇此項
Q: What type of modules does your project use?
JavaScript modules (import/export) 選擇此項
CommonJS (require/exports)
None of these
Q: Which framework does your project use?
React
Vue.js 選擇此項
None of these
Q: Does your project use TypeScript?
No
Yes 選擇此項
Q: Where does your code run?
Browser 選擇此項
Node
Q: How would you like to define a style for your project?
Use a popular style guide 選擇此項
Answer questions about your style
Inspect your JavaScript file(s)
Q: Which style guide do you want to follow?
Airbnb: github.com/airbnb/java…
Standard: github.com/standard standard 選擇此項
Google: github.com/google/esli…
Q: What format do you want your config file to be in?
JavaScript 選擇此項
YAML
JSON
Q: Would you like to install them now with npm?
No
Yes 選擇此項
./eslintrc.js rules 添加
rules: {
'vue/no-multiple-template-root': 'off'
}
prettier
npm i -D prettier eslint-plugin-prettier eslint-config-prettier
ESLint 配置
// .eslintrc.js 的 extends 最後添加 'plugin:prettier/recommended'
extends: ['plugin:vue/essential', 'standard', 'plugin:prettier/recommended'],
添加.prettierrc文件
{
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"semi": false,
"trailingComma": "none"
}
刪除舊的 App.vue 組件, 創建新的 App.tsx 組件
修改 main.ts 的 App 組件的路徑
修改 index.html 中的 main.js --> main.ts
Problems
目前 Vue3 對 ts 的支持度還沒有達到100%, 仍存在一些問題(截至2021/05/23) 例如:
tsx 代碼無法熱更新,需手動刷新
<script lang="tsx">
defineComponent({
setup(props) {
return () => (
<div>the text here won't change with HMR</div>
)
}
})
</script>
函數形式的屬性默認值會干擾typescript類型推斷,需改為箭頭函數
// ❎ 会干扰typescript类型推断
export default defineComponent({
props: {
objectProp: {
type: Object,
default() {
return {}
}
},
arrayProp: {
type: Array,
default() {
return []
}
}
}
})
// ✅ 使用箭头函数
export default defineComponent({
props: {
objectProp: {
type: Object,
default: () => ({})
},
arrayProp: {
type: Array,
default: () => []
}
}
})
yarn add typescript @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint eslint-plugin-vue -D
css方案
因為使用了jsx/tsx所以css就需要寫在單獨的css文件裡了,常用的方案有CssModules ,CssInJs,sass。我個人推薦CssModules。
CssInJs,寫起來很爽但是維護起來除了代碼變長還犧牲了css類名語義化,維護成本比較高。
vite因為是基於瀏覽器的模塊加載,所以並不推薦使用sass,但是如果你倔強非要使用也可以,引入sass即可,注意不是node-sass。
為了讓 vue 認得 tsx 必須要安裝 @vitejs/plugin-vue-jsx
修改 vite.config.js
安裝 router
npm i vue-router@next
安裝 vuex
npm install vuex@next
export default () => {
return <div>hello world for tsx</div>
}
------------------------
import { defineComponent, ref } from 'vue';
export default defineComponent({
props: {
},
setup(props) {
let message = ref("123");
setTimeout(() => {
console.log("hello");
message.value = "Hello";
}, 1000 * 3);
return () => (
<div>hello world for tsx world! '{ message.value }'</div>
);
}
})
-------------------------
使用 router
import { RouterLink, RouterView } from 'vue-router'
export default () => {
return (<div>
<p>
<RouterLink to="/page">page</RouterLink>
</p>
<RouterView />
</div>)
}
import { createApp } from 'vue'
import App from './App'
createApp(App).mount('#app')
{
"name": "starter",
"version": "0.0.0",
"license": "mit",
"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview"
},
"dependencies": {
"vue": "^3.0.5"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^4.24.0",
"@typescript-eslint/parser": "^4.24.0",
"@vitejs/plugin-vue": "^1.2.2",
"@vitejs/plugin-vue-jsx": "^1.1.4",
"@vue/compiler-sfc": "^3.0.5",
"eslint": "^7.27.0",
"eslint-config-standard": "^16.0.2",
"eslint-plugin-import": "^2.23.3",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.3.1",
"eslint-plugin-vue": "^7.9.0",
"path": "^0.12.7",
"typescript": "^4.2.4",
"vite": "^2.3.3"
}
}
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../page/Home'
export default createRouter({
history: createWebHistory(),
routes: [
{
path: '/home',
component: Home
},
{
path: '/VueFile',
name: 'VueFile',
component: import('../page/VueFile.vue')
}
]
})
import { defineComponent, ref } from 'vue'
import { User } from '../model/User.face'
export default defineComponent({
props: {
user: {
type: Object as () => User,
required: true
}
},
setup(popps) {
const age = ref(popps.user.age)
return (
<div>
<p>
有狀態元件
name:{popps.user.name} -- age:{age}
</p>
<button
onClick={() => {
age.value++
}}
>
add age
</button>
</div>
)
}
})
import { User } from '../model/User.face'
export default ({ name, age }: User) => {
return (
<div>
<p>無狀態元件</p>
name:{name}
age:{age}
</div>
)
}
import { createStore } from 'vuex'
export interface State {
count: number
}
export const CountStore = createStore<State>({
state: {
count: 0
}
})
declare module '*.vue'
{
"include": ["./src/**/*.ts", "./src/**/*.tsx"],
"compilerOptions": {
"jsx": "preserve",
"importHelpers": true,
"target": "es2020",
"module": "commonjs",
"experimentalDecorators": true,
"sourceMap": true,
"strict": true,
"noUnusedLocals": true,
"noImplicitReturns": true,
"moduleResolution": "node",
"esModuleInterop": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
"lib": ["esnext", "dom", "dom.iterable", "scripthost"]
}
}
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
import path from "path";
export default defineConfig({
plugins: [
vue(),
vueJsx({})
],
esbuild: {
jsxFactory: "h",
jsxFragment: "Fragment",
},
resolve: {
alias: {
"@": path.resolve(__dirname, "src"),
},
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment