前端會客廳第一期(中)B站地址javascript
前端會客廳是我和winter設計的一檔技術節目,每期會邀請一個嘉賓,暢聊前端技術,廢話很少說,尤大上篇很受歡迎,中篇也上線拉,配套代碼演示 至關於一個買家秀, 代碼實操我最近會錄製視頻放B站,歡迎關注html
其實Vue2如今就有一個全局的方法,方法叫作Vue.observable。 這個其實就是跟Vue3的這個reactive,是同樣的,前端
it('should observe basic properties', () => {
let dummy
const counter = reactive({ num: 0 })
effect(() => (dummy = counter.num))
expect(dummy).toBe(0)
counter.num = 7
expect(dummy).toBe(7)
})
複製代碼
reactive負責對象等負責數據,ref負責基本數據變成響應式 好比數字和字符串,effect負責反作用,這三個概念就是響應式的核心,並且ref和reactive還有一點點小區別vue
reactive直接遍歷對象+Proxy, ref其實也能夠用reactive實現,不過ref只用到了valute屬性,因此徹底可使用get和set來實現依賴收集和通知,有更好的性能java
function createRef(rawValue: unknown, shallow = false) {
if (isRef(rawValue)) {
return rawValue
}
let value = shallow ? rawValue : convert(rawValue)
const r = {
__v_isRef: true,
get value() {
track(r, TrackOpTypes.GET, 'value')
return value
},
set value(newVal) {
if (hasChanged(toRaw(newVal), rawValue)) {
rawValue = newVal
value = shallow ? newVal : convert(newVal)
trigger(
r,
TriggerOpTypes.SET,
'value',
__DEV__ ? { newValue: newVal } : void 0
)
}
}
}
return r
}
複製代碼
effect其實並不會在咱們每次全部的reactive對象發生變化的時候都執行。 他是會只有在這個counter.num有變化的時候纔會執行一次。 因此這樣實際上是用了一個比較巧妙的辦法去監聽了變化 而後這個背後就是用proxy去作,並且若是數據是深層嵌套的,Proxy只會在獲取數據的時候,纔回去遞歸的用proxy,而不是vue2的首次渲染就所有定義好,這也是Vue3性能提高的一個緣由react
if (isObject(res)) {
// Convert returned value into a proxy as well. we do the isObject check
// here to avoid invalid value warning. Also need to lazy access readonly
// and reactive here to avoid circular dependency.
return isReadonly ? readonly(res) : reactive(res)
}
複製代碼
咱們設計一個drag的小方塊,邏輯很簡單,就是能夠把div拖着亂跑,可是每次刷新, 小方塊會回到初始狀態,咱們若是想加入一個數據同步到localStorage的例子,用reactive和effect就能夠實現一個基本無注入的同步函數git
import {reactive, ref, effect} from "@vue/reactivity";
export default function LocalStorage(key, defaultValue){
let data = reactive({});
Object.assign(data, localStorage[key] && JSON.parse(localStorage[key]) || defaultValue);
effect(() => localStorage[key] = JSON.stringify(data));
return data;
}
複製代碼
export default {
data: () => ({
pos: LocalStorage("pos", {x:20, y:20})
}),
}
複製代碼
只在data這裏加了一個函數設置了key,就能夠實現data數據和localStorage的同步了,有了這個腦洞,咱們其實能夠作不少事github
這個沒啥多說得了,社區對比的文章也不少了,主要就是能夠把生命週期,響應式數據,操做函數,所有抽離再一個內部函數,因此vue3的組件就能夠無限的拆分,而且數據來源還能夠異常清晰ajax
好比咱們的todoMvc加一個功能,滾動一段距離後,上面的輸入框就fixed再頂部,用composition api就能夠把這個功能完整的抽離vuex
import { ref, onMounted, onUnmounted } from 'vue'
export default function useScroll() {
const top = ref(0)
function update(e) {
top.value = window.scrollY
}
onMounted(() => {
window.addEventListener('scroll', update)
})
onUnmounted(() => {
window.removeEventListener('scroll', update)
})
return { top }
}
複製代碼
模板中直接使用
const {x,y} = useMouse()
複製代碼
<header class="header" :class="{fixed:top>130}">
複製代碼
可維護性直線提高,而且還能夠有效的把一個功能相關的數據都放在一塊兒,避免了vue2代碼維護的上下反覆橫條,官方經典的圖以下
一個顏色是一個功能,能夠看出vue3的代碼組織更爲合理
可是vue2的option api也不是徹底放棄,由於option的配置,更符合人的心智模型,啥玩意都是this.x 因此小程序option很合適,大型程序composition更利於組織和調試
還能夠直接看下官方吐槽的代碼
優化以後的composition版本 優雅程度直線上升
export default {
setup () {
// Network
const { networkState } = useNetworkState()
// Folder
const { folders, currentFolderData } = useCurrentFolderData(networkState)
const folderNavigation = useFolderNavigation({ networkState, currentFolderData })
const { favoriteFolders, toggleFavorite } = useFavoriteFolders(currentFolderData)
const { showHiddenFolders } = useHiddenFolders()
const createFolder = useCreateFolder(folderNavigation.openFolder)
// Current working directory
resetCwdOnLeave()
const { updateOnCwdChanged } = useCwdUtils()
// Utils
const { slicePath } = usePathUtils()
return {
networkState,
folders,
currentFolderData,
folderNavigation,
favoriteFolders,
toggleFavorite,
showHiddenFolders,
createFolder,
updateOnCwdChanged,
slicePath
}
}
}
複製代碼
vue3的composition和React Hooks只是長的同樣,內部實現機制徹底不一樣,能夠算是雷鋒和雷峯塔的區別,Hooks每次render都會執行一次,composition 是隻調用一次, reactivity獨立後,讓vue3插上了想象力的翅膀,你對新的composition有什麼疑問,歡迎寫在留言區一塊兒討論
第二期嘉賓是周愛民老師,會深刻聊js,歡迎關注,持續更新