[toc]
### 1問: vue3和vue2有哪些不同?
> 1. 響應(yīng)式系統(tǒng)的重構(gòu),使用proxy替換Object.defineProperty屬性召廷,優(yōu)勢:
? ? - Proxy可直接監(jiān)聽 對(duì)象`添加/刪除`屬性;
? ? - Proxy直接監(jiān)聽 數(shù)組的變化
? ? - Proxy監(jiān)聽的目標(biāo)是對(duì)象本身锣笨,不需要像Object.defineProperty那樣遍歷每個(gè)屬性,有一定的性能提升
2. 新增`組合式API`(Composition API),更好的邏輯重用和代碼組織:
? ? - setup配置
? ? - ref與reactive
? ? - watch與watchEffect
? ? - provide與inject
3. 重構(gòu)虛擬 DOM, diff算法
4. 生命周期更名
? ? - beforeDestroy改名為 beforeUnmount
? ? - destroyed改名為 unmounted
```js
// Vue3.0也提供了 Composition API 形式的生命周期鉤子孙咪,與Vue2.x中鉤子對(duì)應(yīng)關(guān)系如下:
beforeCreate ===> setup()
created? ? ? ===> setup()
beforeMount? ===> onBeforeMount
mounted? ? ? ===> onMounted
beforeUpdate ===> onBeforeUpdate
updated? ? ? ===> onUpdated
beforeUnmount===> onBeforeUnmount
unmounted? ? ===> onUnmounted
```
4. 新的內(nèi)置組件:
? ? - Fragment
? ? - Teleport
? ? - Suspense
5. 移除的部分:
? ? - 移除v-on.keyCode修飾符,同時(shí)也不再支持config.keyCodes
? ? - 移除v-on.native修飾符,
? ? - 移除過濾器(filter)
? ? - `不`再建議使用mixins, 組合式函數(shù)本身就是更好的mixin代替品
### 2問: Vue3.0中的響應(yīng)式原理是什么巡语?vue2的響應(yīng)式原理是什么翎蹈?
#### vue2.x的響應(yīng)式原理
- 對(duì)象類型:通過Object.defineProperty()對(duì)屬性的讀取、修改進(jìn)行攔截(數(shù)據(jù)劫持)
- 數(shù)組類型:通過重寫更新數(shù)組的一系列方法來實(shí)現(xiàn)攔截男公。(對(duì)數(shù)組的變更方法進(jìn)行了包裹)荤堪。
- 存在問題:
? ? - 新增屬性、刪除屬性, 界面不會(huì)更新枢赔。
? ? - 直接通過下標(biāo)修改數(shù)組, 界面不會(huì)自動(dòng)更新澄阳。
- 追問: vue2如何解決這些問題? 答: `$set`
#### vue3.0的響應(yīng)式原理
- 通過Proxy(代理): 攔截對(duì)象中任意屬性的變化, 包括:屬性值的讀寫、添加踏拜、刪除等碎赢。
- 通過Reflect(反射): 對(duì)源對(duì)象的屬性進(jìn)行操作。
```js
new Proxy(data, {
? ? // 攔截讀取屬性值
? ? get (target, prop) {
? ? ? ? return Reflect.get(target, prop)
? ? },
? ? // 攔截設(shè)置屬性值或添加新屬性
? ? set (target, prop, value) {
? ? ? ? return Reflect.set(target, prop, value)
? ? },
? ? // 攔截刪除屬性
? ? deleteProperty (target, prop) {
? ? ? ? return Reflect.deleteProperty(target, prop)
? ? }
})
proxy.name = 'tom'?
```
- 存在問題: 解決了vue2響應(yīng)式的短板, 但是也存在兼容性問題(新特性, 老瀏覽器不支持)
### 3問: 有哪些vue3響應(yīng)性判斷函數(shù)?
- isRef: 檢查一個(gè)值是否為一個(gè) ref 對(duì)象
- isReactive: 檢查一個(gè)對(duì)象是否是由 reactive 創(chuàng)建的響應(yīng)式代理
- isReadonly: 檢查一個(gè)對(duì)象是否是由 readonly 創(chuàng)建的只讀代理
- isProxy: 檢查一個(gè)對(duì)象是否是由 reactive 或者 readonly 方法創(chuàng)建的代理
### 4問: setup函數(shù)怎么用?
- setup使用:
```js
setup(props, context) {
? ? /*** Setup props */
? ? // 請注意如果你解構(gòu)了 props 對(duì)象速梗,解構(gòu)出的變量將會(huì)丟失響應(yīng)性, 推薦使用props.title形式
? ? console.log(props.title)
? ? // 將 `props` 轉(zhuǎn)為一個(gè)其中全是 ref 的對(duì)象肮塞,然后解構(gòu)
? ? const { title } = toRefs(props)
? ? // `title` 是一個(gè)追蹤著 `props.title` 的 ref
? ? console.log(title.value)
? ? // 或者襟齿,將 `props` 的單個(gè)屬性轉(zhuǎn)為一個(gè) ref
? ? const title = toRef(props, 'title')
? ? /*** Setup 上下文 */
? ? // 透傳 Attributes(非響應(yīng)式的對(duì)象,等價(jià)于 $attrs)
? ? console.log(context.attrs)
? ? // 插槽(非響應(yīng)式的對(duì)象枕赵,等價(jià)于 $slots)
? ? console.log(context.slots)
? ? // 觸發(fā)事件(函數(shù)猜欺,等價(jià)于 $emit)
? ? console.log(context.emit)
? ? // 暴露公共屬性(函數(shù))
? ? console.log(context.expose)
? }
```
- 注意點(diǎn), 當(dāng)使用\<script setup\>語法糖時(shí):
父組件通過模板引用訪問該組件的實(shí)例時(shí),將僅能訪問 expose 函數(shù)暴露出的內(nèi)容
### 5問: Composition API 和 React Hook 很像, 它們有什么區(qū)別?
是很像, Composition API 誕生之初就借鑒了React Hook, 同時(shí)避免了reack Hook的短板限制:(吹爆vue3好嗎)
#### reack Hook的限制:
- 不能在循環(huán)中拷窜、條件开皿、調(diào)用嵌套函數(shù) Hook
- 你必須確保它總是在你這邊 React Top level 調(diào)用函數(shù) Hook
- useEffect、useMemo 依賴關(guān)系必須手動(dòng)確定
####? Composition API 相比于 React Hook優(yōu)點(diǎn):
- Compositon API 不必?fù)?dān)心調(diào)用的順序篮昧,它也可以在循環(huán)中赋荆、條件、在嵌套函數(shù)中使用
- React Hook 每次重新渲染時(shí)懊昨,都需要調(diào)用 Hook, 而vue3在setup函數(shù)中糠睡,一個(gè)組件實(shí)例只調(diào)用一次setup,性能相對(duì)react hook較高
- vue響應(yīng)式系統(tǒng)自動(dòng)實(shí)現(xiàn)依賴關(guān)系收集疚颊,而且組件的性能優(yōu)化是由 Vue 內(nèi)部完成的狈孔,而 React Hook 的依賴關(guān)系需要手動(dòng)傳遞,并且依賴關(guān)系的順序必須得到保證材义,讓路 useEffect均抽、useMemo 等等,否則組件性能會(huì)因?yàn)橐蕾囮P(guān)系不正確而下降其掂。
### 6問: ref 和 reactive 區(qū)別?
1. 簡單來說, ref通常用來定義`基本類型`數(shù)據(jù), reactive用來定義`對(duì)象(或者數(shù)組)`類型數(shù)據(jù)
注: ref也可以用來定義對(duì)象(或數(shù)組)類型數(shù)據(jù), 它內(nèi)部會(huì)自動(dòng)通過reactive轉(zhuǎn)為代理對(duì)象油挥。
2. 使用方面: ref 操作數(shù)據(jù)`需要.value`取值,template模板中不需要款熬。
reactive都`不需要.value`取值
3. 數(shù)據(jù)傳遞方面:
解構(gòu)賦值會(huì)使reactive丟失響應(yīng)性, 而{ref(1), ref(2)}不會(huì)
4. 原理角度:
ref通過Object.defineProperty()的get與set來實(shí)現(xiàn)響應(yīng)式(數(shù)據(jù)劫持)深寥。
reactive通過使用Proxy來實(shí)現(xiàn)響應(yīng)式(數(shù)據(jù)劫持), 并通過Reflect操作源對(duì)象內(nèi)部的數(shù)據(jù)。
### 7問: watch 和 watchEffect
- watch使用:
```js
// sum 可以是ref, reactive, 或者是一個(gè)getter函數(shù), 或者以上組成的數(shù)組
watch(sum,(newValue,oldValue)=>{
? ? console.log('sum變化了',newValue,oldValue)
},{immediate:true})
```
- 注意點(diǎn): 當(dāng)watch監(jiān)聽的是reactive時(shí)
? ? - 強(qiáng)制開啟深度監(jiān)聽(deep: true失效)
? ? - oldValue無法正確獲取, (oldValue===newValue)
- watchEffect使用:
```js
const stop = watchEffect(()=>{
? ? const x1 = sum.value
? ? const x2 = person.age
? ? console.log('watchEffect配置的回調(diào)執(zhí)行了')
})
// 如需要
stop()
```
- 與watch不同點(diǎn):
? ? - watch需指明監(jiān)聽的屬性
? ? - watchEffect無需指明需要監(jiān)聽的屬性,vue的響應(yīng)性系統(tǒng)自動(dòng)進(jìn)行依賴收集,
只要所指定的回調(diào)中用到的數(shù)據(jù)發(fā)生變化贤牛,則直接重新執(zhí)行回調(diào)
### 8問: vue3的Composition API 相比于2的Options API, 有什么優(yōu)勢嗎?
1. Options API 存在的問題, 新增或者修改一個(gè)需求惋鹅,就需要分別在data,methods殉簸,computed里修改 闰集。而組合式API這種情況只需要在特定的代碼塊里新增修改, `代碼組織結(jié)構(gòu)更優(yōu)雅`
2. 組合式API 代碼粒度更加細(xì)膩(相較于組件), use函數(shù)使得`邏輯提取和重用`的成本更低, 代碼維護(hù)性更強(qiáng)
3. 開發(fā)者可以只需關(guān)注`實(shí)際的業(yè)務(wù)邏輯`, 而不是散落在各處(監(jiān)視、計(jì)算般卑、方法 Option)業(yè)務(wù)邏輯附屬品
### 9問: 什么是SSR(服務(wù)端渲染),原理是什么? 好處有哪些?
- ssr全稱server side render, 前端頁面的產(chǎn)生是由服務(wù)器端生成的武鲁,我們就稱之為服務(wù)端渲染。
- 對(duì)比客戶端渲染?(client side render, CSR)
CSR執(zhí)行流程:瀏覽器加載html文件 -> 瀏覽器下載js文件 -> 瀏覽器運(yùn)行vue代碼 -> 渲染頁面
SSR執(zhí)行流程:瀏覽器加載html文件 -> 服務(wù)端裝填好內(nèi)容 -> 返回瀏覽器渲染
- 使用SSR的好處?(何時(shí)該使用SSR?):
? ? 1. 對(duì)SEO有利:搜索引擎的爬蟲爬取你的頁面信息蝠检,因?yàn)榇蠖鄶?shù)爬蟲并不支持等待前端獲取數(shù)據(jù)后再爬取數(shù)據(jù)的沐鼠,而有了SSR以后,這些抓取工具就可以立刻得到完整的HTML結(jié)構(gòu)化數(shù)據(jù),從而被納入搜索引擎饲梭。
? ? 2. 更短的白屏?xí)r間:服務(wù)端渲染并不需要加載和執(zhí)行大量的js腳本, 直接渲染服務(wù)端給出的html字符串, 從而縮短首屏加載時(shí)間
- 不好的地方: 前后端分工搭配復(fù)雜,? 原本一個(gè)頁面, 同時(shí)由前后端繪制填充
- 服務(wù)端渲染 (SSR): [vue3官方文檔](https://cn.vuejs.org/guide/scaling-up/ssr.html#rendering-an-app)
### 10問: 還能想到Vue3其他不同于vue2的細(xì)節(jié)點(diǎn)嗎?(考察寬度, 使用度)
- Vue3.0中對(duì)這些API做出了調(diào)整:全局API的轉(zhuǎn)移
<table><thead><tr><th>2.x 全局 API(<code>Vue</code>)</th><th>3.x 實(shí)例 API (<code>app</code>)</th></tr></thead><tbody><tr><td>Vue.config.xxxx</td><td>app.config.xxxx</td></tr><tr><td>Vue.config.productionTip</td><td><strong>移除</strong></td></tr><tr><td>Vue.component</td><td>app.component</td></tr><tr><td>Vue.directive</td><td>app.directive</td></tr><tr><td>Vue.mixin</td><td>app.mixin</td></tr><tr><td>Vue.use</td><td>app.use</td></tr><tr><td>Vue.prototype</td><td>app.config.globalProperties</td></tr></tbody></table>
- 簡化了`slot插槽`使用, vue2中作用域插槽: 必須兩個(gè)屬性: slot='slotName' slot-scope='prop'; vue3則是`#slotName='prop'`
- vue實(shí)例的創(chuàng)建方法不同:
```js
/** vue2 **/
import Vue from 'vue'
...
new Vue({
? el: '#app',
? router,
? store,
? axios,
? render: h => h(App)
})
/** vue3 **/
import { createApp } from 'vue'
// 從一個(gè)單文件組件中導(dǎo)入根組件
import App from './App.vue'
const app = createApp(App)
```
- 支持`組件上使用 v-model`, 實(shí)現(xiàn)雙向綁定
等等...