3.0的目標css
- 更小
- 更快
- 增強 TypeScript 支持
- 增強 API 設計一致性
- 提升自身可維護性
- 開放更多底層功能
什麼是Hooks? html
hooks翻譯過來是鉤子的意思,這個可能有一些模糊,簡單點說hooks就是一個函數(能夠複用的函數)例如:業務中很難避免的一個問題就是-- 邏輯複用,一樣的功能,一樣的組件,在不同的場合下,咱們有時候不得不去寫2+次,爲了不耦合咱們出現了一些概念(mixin,高級組件,slot插槽)。
上述這些方法均可以實現邏輯上的複用,可是都有一些額外的問題:vue
mixin的問題:react
- 不一樣的mixin中的方法,屬性可能會相互衝突(命名空間衝突);
- mixin很是多時,會形成數據來源不清晰
HOC的問題:webpack
- 須要在原組件上進行包裹或者嵌套,將會產生很是多的嵌套,調試起來不容易;
- props命名空間衝突(多個高級組件的props衝突)
- props 數據來源不清晰(不知道這個屬性究竟是那個高級組件傳遞的)
- 額外的組件實例消耗性能
做用域插槽:web
沒有命名衝突和數據來源不清晰的問題,可是建立了額外的組件
因此,hook的出現是劃時代的,它經過function抽離的方式,實現了複雜邏輯的內部封裝在vue中的hooks主要是爲了邏輯代碼的複用不存在命名衝突,數據來源不清晰的問題減少了代碼體積:由於在打包時候咱們用了那些函數就會打包那些不用的不會打包,並且在打包的時候會對函數進行混淆壓縮變得更小沒有this的煩惱,不須要經過this訪問一些內容了。 npm
什麼是TypeScript?json
其實TypeScript並非一門新的語言,它是 JavaScript 類型的超集,typeScript那並非一個新語言,能夠理解爲增強JavaScript的buff,TypeScript最大的優點源於強大的類型系統,還有就是在編寫代碼的時候就能夠檢測出咱們可能由於粗心形成的沒必要要的錯誤。
爲何要學習TypeScript ?segmentfault
- 將來趨勢,目前來看發展,和應用趨勢很快
- vue3.0發佈後,基本就離不開ts了
- 使用 TypeScript 能夠幫助咱們防止在編寫 JavaScript 代碼時由於數據類型的轉換形成的意想不到的錯誤。提早幫咱們發現代碼出現錯的風險。
- 團隊成員使用 JavaScript 時很容易瞎寫,不受規範約束。可是若是使用TypeScript那你們都不得不遵照規範。
- TypeScript 緊跟 JavaScript 的發展,ES7 、ES八、ES9 相關語言的新特性都支持,比瀏覽器支持的速度更快。
什麼樣的項目須要TypeScript ?api
- 團隊多人開發的大項目
- 開源項目
- 企業對代碼有高質量要求的項目
如何使用Ts:
Vue3.0 最重要的就是 RFC,即 Function-based API。Vue3.0 將拋棄以前的 Class API 的提案,選擇了 Function API。目前,vue 官方 也提供了 Vue3.0 特性的嚐鮮版本,前段時間叫 vue-function-api,目前已經更名叫 composition-api。
使用官方腳手架Vue-cli建立一個ts項目
npm install -g @vue/cli yarn global add @vue/cli
新的 VueCLI工具容許開發者 使用 TypeScript 集成環境 建立新項目。只需運行 vue create tsvue3demo。而後,命令行會要求選擇預設。使用箭頭鍵選擇 Manually select features。
這樣一個可使用ts的vue基礎架構就構建完成了
目錄架構
. ├── README.md ├── babel.config.js ├── package.json ├── postcss.config.js ├── public │ ├── favicon.ico │ └── index.html ├── src │ ├── App.vue │ ├── assets │ │ └── logo.png │ ├── components │ │ └── HelloWorld.vue │ ├── main.ts │ ├── router │ │ └── index.ts │ ├── shims-tsx.d.ts 容許你以 .tsx結尾的文件,在 Vue項目中編寫 jsx代碼 │ ├── shims-vue.d.ts 主要用於 TypeScript 識別 .vue 文件 │ ├── store │ │ └── index.ts │ └── views │ ├── About.vue │ └── Home.vue ├── tsconfig.json └── yarn.lock
在這個建立好的目錄中咱們打開 HelloWord.vue 文件能夠看到不同的組件寫法
<template> <div class="hello"> <h1>{{ msg }}</h1> ... </div> </template> <script lang="ts"> import { Component, Prop, Vue } from 'vue-property-decorator' @Component export default class HelloWorld extends Vue { @Prop() private msg!: string; } </script>
以上的寫法是在vue3.0之前,強化Vue組件使用typeScript的寫法
須要引入:
vue-class-component:強化 Vue 組件,使用 TypeScript/裝飾器 加強 Vue 組件vue-property-decorator:在 vue-class-component 上加強更多的結合 Vue 特性的裝飾器ts-loader:TypeScript 爲 Webpack 提供了 ts-loader,其實就是爲了讓webpack識別 .ts .tsx文件tslint-loader跟tslint:我想你也會在.ts .tsx文件 約束代碼格式(做用等同於eslint)tslint-config-standard:tslint 配置 standard風格的約束
可是在vue3.0裏面廢棄了class component
Vue3.0的用法
Vue3.0尚未正式發佈,可是官方提供了Vue 2.x 可以提早體驗此API的庫@vue/composition-api
安裝
npm i @vue/composition-api -S
使用
import Vue from 'vue' import VueCompositionApi from '@vue/composition-api' Vue.use(VueCompositionApi)
若是項目是用的 TS,須要使用 createComponent 來定義組件,這樣你才能使用類型推斷,若是沒有使用,可直接拋出一個對象
<template> <div id="app"> </div> </template> <script lang="ts"> import { createComponent } from '@vue/composition-api' export default createComponent({ ... }) </script>
實例:這是VueConf 2019尤大大在介紹的時候給出的一個例子,改爲ts版本
<template> <div id="app"> <div class="hooks-one"> <h2>{{ msg }}</h2> <p>count is {{ count }}</p> <p>plusOne is {{ plusOne }}</p> <button @click="increment">count++</button> </div> <!-- <router-view/> --> </div> </template> <script lang="ts"> import { ref, computed, watch, onMounted, Ref, createComponent } from '@vue/composition-api' interface Props { name: string } export default createComponent({ props: { name: { type: String, default: 'ssss' } }, components: {}, setup (props: Props, context) { const count: Ref<number> = ref(0) // computed const plusOne = computed(() => count.value + 1) // method const increment = () => { count.value++ } // watch watch(() => count.value * 2, val => { console.log(`count * 2 is ${val}`) }) // 生命週期 onMounted(() => { console.log('onMounted') }) // expose bindings on render context return { count, plusOne, increment, msg: `hello ${props.name}` } } }) </script>
詳解:setupsetup函數是Vue Function API 構建的函數式寫法的主邏輯,當組件被建立時,就會被調用,函數接受兩個參數,分別是父級組件傳入的props和當前組件的上下文context。context上下文(this的替代者能夠理解爲),setup 是在組件實例被建立時, 初始化了 props 以後調用,處於 created 前。setup() 和 data() 很像,均可以返回一個對象,而這個對象上的屬性則會直接暴露給模板渲染上下文:
<template> <div id="app"> {{ msg }} {{ count }} </div></template><script lang="ts">import { createComponent } from '@vue/composition-api'export default createComponent({ props: { name: String }, setup (props) { const count: Ref<number> = ref(0) return { msg: `hello ${props.name}`, count } }})</script>
組件 API(Composition API)
組件 API 是 Vue 的下一個主要版本中最經常使用的討論和特點語法。這是一種全新的邏輯重用和代碼組織方法。當前,咱們使用所謂的 Options API 構建組件。爲了向 Vue 組件添加邏輯,咱們填充(可選)屬性,例如 data、methods、computed等。這種方法的最大缺點是其自己並非有效的 JavaScript 代碼。你須要確切地知道模板中能夠訪問哪些屬性以及 this 關鍵字的行爲。在後臺,Vue 編譯器須要將此屬性轉換爲工做代碼。所以咱們沒法從自動建議或類型檢查中受益。組件 API 旨在經過將組件屬性中當前可用的機制公開爲 JavaScript 函數來解決這個問題。Vue 核心團隊將組件 API 描述爲 「一組基於函數的附加 API,能夠靈活地組合組件邏輯。」 用組件 API 編寫的代碼更具備可讀性
reactive和ref
reactive(): 轉換響應式對象
ref(): 轉換原始類型爲響應式對象
二者的區別reactive 代理初始化一個對象,ref 只是一個 .value 值,在函數中使用都要一直使用 .value 引着
<template> <div id="app"> <div class="hooks-one"> {{state.double}} {{state.count}} <p>count is {{ count }}</p> <button @click="increment">count++</button> </div> <!-- <router-view/> --> </div> </template> <script lang="ts"> import { ref, computed, reactive, Ref, createComponent } from '@vue/composition-api' interface State { count: number, double: number } export default createComponent({ setup (props, context) { const count: Ref<number> = ref(0) const state: State = reactive({ count: 0, double: computed(() => state.count * 2) }) // method const increment = () => { count.value++ // 須要.value獲取,改變 state.count++ } // expose bindings on render context return { increment, state } } }) </script>
watch & computed
watch和computed的基本概念與 Vue 2.x 的watch和computed一致,watch能夠用於追蹤狀態變化來執行一些後續操做,computed用於計算屬性,用於依賴屬性發生變化進行從新計算。computed返回一個只讀的包裝對象,和普通包裝對象同樣能夠被setup函數返回,這樣就能夠在模板上下文中使用computed屬性。能夠接受兩個參數,第一個參數返回當前的計算屬性值,當傳遞第二個參數時,computed是可寫的。=
生命週期
全部現有的生命週期都有對應的鉤子函數,經過onXXX的形式建立,但有不一樣的是,destoryed鉤子函數須要使用unmounted代替,刪除了onBeforeCreate和onCreated:
import { onMounted, onUpdated, onUnmounted, createComponent } from '@vue/composition-api';export default createComponent({ setup() { onMounted(() => { console.log('mounted!'); }); onUpdated(() => { console.log('updated!'); }); // destroyed 調整爲 unmounted onUnmounted(() => { console.log('unmounted!'); }); },});
參考:
https://zhuanlan.zhihu.com/p/68477600
https://www.yuque.com/vueconf/2019
https://vue-composition-api-rfc.netlify.com/api.html
https://juejin.im/post/5dca71f8f265da4cef191581
https://juejin.im/post/5d836458f265da03d871f6e9
https://segmentfault.com/a/1190000020205747?utm_source=tag-newest