# Vue 3 + TypeScript + TSX 上手體驗
# 建立專案
用 vue-cli (opens new window) 建立一個專案,接著加入 vue-cli-plugin-vue-next (opens new window) 這 plugin
用 vite (opens new window) 這尤大大的新玩具,並搭配 create-vite-app (opens new window) 快速建立 Vue 3 的專案,基本上一直下一步就可以完成了
yarn create vite-app test-vite
cd test-vite
預設 vite 是沒有 typescript 的,所以需要手動加上
yarn add --dev typescript
# 改寫 js 進入點
/src/main.js
重命名成 /src/main.ts/index.html
將 main.js
改成 main.ts
<script type="module" src="/src/main.ts"></script>
# 改寫 App.vue
/src/App.vue
重命名成 /src/App.tsx
並改寫內容
import { defineComponent } from 'vue'
import HelloWorld from '../HelloWorld';
import imgLogo from './assets/logo.png';
export default defineComponent({
name: 'Root',
setup() {
return () => (
<>
<img alt="Vue logo" src={imgLogo} />
<HelloWorld msg="Hello Vue 3.0 + Vite" />
</>
)
},
})
這邊有幾個重點改寫:
- 使用 Composition API
setup
並使用 TSX 寫 VNode - 支援使用 Fragment TSX (可以不用每個 Component 都一定要有 root DOM,但整個 Vue App 一一定要至少一個 DOM)
- Component
HelloWorld
有型別提示 (ex:msg
) - Component
HelloWorld
有型別提示!! - Component
HelloWorld
有型別提示!!! - 原
<img src="./assets/logo.png">
改成用import
resource
# 改寫 HelloWorld.vue
components/HelloWorld.vue
重命名成 components/HelloWorld.tsx
並改寫內容
import { defineComponent, ref } from 'vue';
export default defineComponent({
props: {
msg: String
},
setup(props) {
**** const count = ref(0)
const handleCountButtonClick = () => count.value ++
**** return () => (
<>
<h1>{props.msg}</h1>
<button onClick={handleCountButtonClick}>count is: { count.value }</button>
<p>Edit <code>components/HelloWorld.tsx</code> to test hot module replacement.</p>
</>
)
}
})
改寫重點:
count
使用ref
變成 reactive varhandleCountButtonClick
作為接受按鈕按下事件
# 改寫 HelloWorld Counter
看到他有一個 counter 的按鈕,想說可以把 counter 的邏輯拆出來做成 useCounter
,順便使用 Composition API 實作!
新增 components/Counter.tsx
import { defineComponent, ref } from 'vue';
export const useCounter = (step: () => number) => {
const count = ref(0)
const add = () => count.value += step()
const current = () => count.value
return {
add, current,
}
}
export default defineComponent({
name: 'Counter',
setup(props) {
const { add, current } = useCounter(() => 1)
const handleButtonClick = () => add()
**** return () => (
<button onClick={handleButtonClick}>count is: { current() }</button>
)
}
})
更新 components/HelloWorld.tsx
使用 components/Counter.tsx
import { defineComponent } from 'vue';
import Counter from './Counter';
export default defineComponent({
props: {
msg: String
},
setup(props) {
return () => (
<>
<h1>{props.msg}</h1>
<Counter></Counter>
<p>Edit <code>components/HelloWorld.tsx</code> to test hot module replacement.</p>
</>
)
}
})