掘金的第一篇文章獻給vue3.0,html
vue3.0的正式版發佈有必定的時間了,忙於其餘,雖然好奇但沒有進行比較和學習,終於不負本身「指望」,打敗了「懶惰」,學習相關熟悉的技術新版本,其實入手仍是比較簡單的(坐等打臉),本文主要是筆者本身在學習過程當中的探索;vue
最大的感覺,組合api是將具備獨立功能的函數封裝組合在一塊兒,提升複用性; 後來實際封裝了相關功能,變量較多的狀況下,設計高內聚的功能是很是必要的react
分別用vue2.x以及vue3.x進行了學生列表和老師列表的展現,其代碼功能分部圖以下圖所示es6
vue2.x 學生和老師展現代碼功能圖
api
vue 3.x! 學生和老師展現代碼功能圖 其中不一樣顏色表示頁面中兩個功能的代碼分佈;markdown
根據顏色而言,其實vue2.x的功能相對而言是比較分散的,而vue3.0中的功能和數據定義能夠定義在一個函數中,功能比較集中;所以在進行組合性api的是時候是須要思考如何設計是比較合理的;vue3.x在功能上可以實現高度的一個複用,想到vue.mixin
的方法,實現代碼的複用;數據結構
響應式數據是實現mvvm很是重要的一個部分,在vue3.x中,在支持data
方式定義響應式的數據外,還提供不少可自定義的api;app
在響應式的數據中值得注意的部分 深層次響應仍是淺層次響應;dom
定義響應式數據的一種方式,經過
Proxy
包裝傳入的變量,藉助Proxy提供的set和get方法,實現響應式數據的邏輯異步
setup(props) {
let state =reactive({
msg:{
name:'mafe',
age:24,
},
time: new Date(), //只能進行 賦值更新
list:[
{name:'mfy'},
{name:'mfy1'},
{name:'mfy2'},
]
})
function changeName(){
//定義的是對象可以直接修改賦值
state.msg.name = '333'
//沒法更改state中time的賦值對象
// state.time.setDate(state.time.getDate()+1)
let newDate =new Date(state.time.getTime())
newDate.setDate(state.time.getDate()+1)
state.time = newDate ;//不是對象類型 只能修改數據內容
}
return {
state,
changeName
}
}
複製代碼
state.time = XXX
賦值的方式進行更改;new Date()
進行賦值,獲得的time的原型並不是是Date的,再次修改time的值的時候不能經過setDate
賦值;Proxy
的代理,用於頁面的響應式數據構建;也是定義響應式數據的一種,一般用來定義基礎類型數據,以及獲取dom元素的內容
reactive
一般用於定義對象,在咱們實際的使用過程當中是很是不便捷的,咱們僅僅是想要某個變量實現響應式,ref
是對簡單的值進行監聽;
ref
的本質仍是reactive
,系統會自動根據咱們傳入的值轉換成ref(xxx)->reactive({value:xx})
setup(props) {
// 傳遞一個值
let age = ref(33);
function changeAge(){
age.value +=1;
}
return{
age,
changeAge
}
}
複製代碼
ref 定義的內容:
ref定義對象類型時候更新問題 ref定義的對象類型,若是是隻想更改某一層的變化 須要調用triggerRef進行觸發更新
// 只想更改ref中某一層的變化
msg.value.a = 'myy'
//增長triggerRef 引發視圖的更新
// Vue3 只提供了triggerRef 沒有提供reactRef相關的
triggerRef(msg)
複製代碼
若是參數爲 ref
,則返回內部值,不然返回參數自己。這是 val = isRef(val) ? val.value : val
。
let age = ref(33);
console.log(age)
console.log(unref(age))
複製代碼
ref
類型的數據,vue會自動幫咱們計算.valuereactive
類型的數據,vue不會自動幫咱們計算.value.value
的Vue在解析數據以前,會自動判斷這個數據是不是ref類型的,若是是,則自動添加上.value
,若是不是,則不會自動添加
ref
類型的__v_isRef
來進行判斷的,true
,那麼就表明是一個ref
類型的數據console.log("判斷是不是ref類型數據",isRef(age))
console.log("判斷是不是isReactive類型數據",isReactive(age))
複製代碼
不管是ref仍是reactive的都是遞歸監聽的過程,也就是不管咱們嵌套了多少層級,其每一層的每一個數據都會發生監聽;
let state= reactive({
a:'2',
gf:{
b:'b',
f:'c',
c:{
a:3
}
}
})
// 多個層級 每一個層級內容改變的時候,都會改變;
function changeValue(){
console.log(state)
console.log(state.gf)
}
複製代碼
打印後能夠發如今reactive中定義的對象,發現對象中的每一層對象都是經過Proxy進行代理
let msg = ref({
a:'2',
gf:{
b:'b',
f:'c',
c:{
a:3
}
}
})
function changeRef(){
//直接更改ref
console.log(msg.value)
console.log(msg.value.gf)
}
複製代碼
只監聽對象的第一層,
shallowRef
Vue監聽的是.value
的變化,並非第一層的變化利用shallowRef 和shallowReactive可以改變當前對象的監聽層級
let state = shallowReactive({
a:'2',
gf:{
b:'b',
f:'c',
c:{
a:3
}
}
})
function changeValue(){
console.log(state)
console.log(state.gf)
}
複製代碼
第二層的對象不會包裝成響應式內容
let msg = shallowRef({
a:'2',
gf:{
b:'b',
f:'c',
c:{
a:3
}
}
})
function changeRef(){
console.log(msg)
console.log(msg.value)
console.log(msg.value.gf)
}
複製代碼
注意內容:
msg.value
的時候,其實已經訪問它的值了,天然是沒有內容的;只讀屬性的修改,使用
readonly
防止更改響應式對象
存在一組對象,咱們只能讀取,可是不能更改,所以可使用readonly進行包裹;
let state = readonly({name:'mfy',age:34,attr:{weight:45,height:1.88}})
function changeReadonly(){
state.age = 2; //修改第一層
state.attr.weight = 2; //修改深層
console.log(state)
console.log(isReadonly(state))
}
複製代碼
點擊進行修改時候
const obj = reactive({name:'33'})
console.log(obj)
let state = readonly({name:'mfy',age:34,attr:{weight:45,height:1.88}})
console.log(state)
複製代碼
reactive
定義的參數在Proxy
函數的set支持傳入四個參數readonly
只能收到兩個參數,在set中直接進行警告提示和shallowRef
以及shallowReactive
的性質同樣,只能控制第一層的數據是不可修改的;
let state = shallowReadonly({name:'mfy',age:34,attr:{weight:45,height:1.88}})
console.log(state)
function changeReadonly(){
state.age = 2; //修改第一層
state.attr.weight = 2; //修改第二層
console.log(state)
console.log(state.attr)
}
複製代碼
shllowReadonly
非遞歸包裝,只包裝第一層數據,第二層將不會進行包裝const也是定義的變量不能在修改,可是對於對象除外;
在實際的使用中,咱們可能不只僅是進行一整個屬性進行監聽,有多是單個的屬性進行監聽,所以toRef等給咱們提供了固定屬性進行監聽;
let obj1 = {age:34,name:'mfy'}
let state2 = toRef(obj1,'name')
function changeRef(){
state2.value = 333
console.log('obj1',obj1)
console.log('state2',state2)
}
複製代碼
toRef
修改的值不只僅使定義的值發生了改變,其原始值也發生了改變;
toRef
將某一個對象的屬性變成響應式的,此時修改是會影響到原始值將響應式對象轉化爲普通對象,其中結果對象的每一個
property
都是指向原始對象相應property
的ref
。
let state3 = toRefs(obj1,'name','age')
複製代碼
let obj = {age:34,name:'mfy'}
let state =reactive(obj);
console.log(state)
let state2 = toRefs(state)
console.log(state2)
複製代碼
打印出來state
和state2
state2
中的引用和原始數據類型以及經過reactive
定義的類型都是屬於同一引用關係;即修改obj
、state
、state2
中的任何一個元素屬性值,都會發生改變;
let obj = {age:34,name:'mfy'}
let state =reactive(obj);
console.log(state)
let state2 = toRefs(state)
console.log(state2)
function changeRef(){
//修改值
obj.age = 232323;
console.log('state2',state2)
console.log('state',state)
console.log('obj',obj)
}
複製代碼
使用reactive定義的對象是不具備響應式的,所以在使用的時候沒法進行結構出來使用,而toRefs
能夠定義每一個屬性都是響應式的,
function useFeatureX() {
const state = reactive({
foo: 1,
bar: 2
})
// 返回時轉換爲ref
return toRefs(state)
}
export default {
setup() {
// 能夠在不失去響應性的狀況下破壞結構
const { foo, bar } = useFeatureX()
return {
foo,
bar
}
}
}
複製代碼
被定義的響應式數據,如何找到原始數據呢?
從
reactive
或者ref
中獲得原始數據,主要是作一些不想被監聽的事情(提高性能),每次修改都會被追蹤,都會被更新UI界面,可是是很是消耗性能的,因此有一些操做咱們不須要追蹤,不須要更新ui界面,此時能夠經過toRaw
方法拿到原始數據,對原始數據進行修改,這樣不會被追蹤,不會更新ui界面
//默認狀況下不是一個響應式數據
let obj = {age:34,name:'mfy'}
let state =reactive(obj);
//把建立時候的參數分解出來
let obj2 = toRaw (state); // 和obj是一個樣子
function changeRef(){
//引用修改的內容,頁面不會自動更新 只有經過修改包裝的方法才能更新
obj2.name = 'myy'
//state和obj是引用關係,其中的一個值更改時候,另一個值也會更改
console.log(state)
console.log(obj)
console.log(obj2)
}
複製代碼
toRaw
獲取到的變量,是一個引用的關係對於ref
定義的值,必需要準確的告訴toRaw
是.value
若是經過toRaw
獲取ref
的數據,必須明確告訴ref
是.value
的值 通過Vue
處理以後,.value
中保存的是當初建立時傳入的那個原始數據;
let obj = {age:34,name:'mfy'}
let state =ref(obj);
//把建立時候的參數分解出來
let obj2 = toRaw(state.value); // 必須指定定義的ref內部變量的value
function changeRef(){
obj2.name = 'myy'
console.log('state',state)
console.log('obj',obj)
console.log('obj2',obj2)
}
複製代碼
markRaw 永遠不想被追蹤
let obj = {age:34,name:'mfy'}
//告訴這個對象 永遠不能被監聽
obj = markRaw(obj)
let state =reactive(obj);
function changeRef(){
state.name ='mfy';//監聽到這個的變化
console.log(state)
}
複製代碼
經過markRaw定義的屬性再次被定義成響應式的時候,不管怎樣對state
進行賦值,是沒法更改其內容的;
setup
是vue3.x
中加入的一個新的生命週期,也是組合api的入口,因爲在執行 setup
時還沒有建立組件實例,所以在 setup
選項中沒有this
。這意味着,除了props
以外,你將沒法訪問組件中聲明的任何屬性——本地狀態、計算屬性或方法。
setup
->beforeCreate
-> created
setup
在執行的時候是在beforeCreate
以前,所以是沒法進行獲取到this
的setup(props) {
//定義數據
let age = ref(33)
//定義函數
function changeAge(){
age.value = 333
}
// 必須將變量暴露出去才能進行使用
return{
age,
changeAge
}
}
複製代碼
在setup的函數中,其內部提供了不少的可進行兼容的方法
用於使用計算屬性,能夠直接獲取到當前拼接出來的值
let firstName = ref("馬");
let lastName = ref("fyy")
let fullName = computed(()=> firstName.value + lastName.value)
console.log(fullName)
複製代碼
若想要直接修改computed
的變量,可使用set
的方法,將依賴的屬性的值進行修改;
let age = ref(12)
let ageCom = computed({
get: () => age.value + 1,
set: val => {
age.value = val - 1
}
})
複製代碼
在響應式地跟蹤其依賴項時當即運行一個函數,並在更改依賴項時從新運行它。
let firstName = ref("馬");
let lastName = ref("fyy")
let fullName = computed(()=> firstName.value + lastName.value)
watchEffect(() => {
console.log('%c 內容發生改變了','color:yellow',fullName.value)
})
function changeName(){
firstName.value = 'Ming'+Math.random()
}
複製代碼
每次watchEffect
裏面的內容發生改變的時候都會觸發;
watch API
與選項式 API this.$watch
(以及相應的 watch 選項) 徹底等效。watch
須要偵聽特定的 data
源,並在單獨的回調函數中反作用。默認狀況下,它也是惰性的——即,回調是僅在偵聽源發生更改時調用。 與 watchEffect
比較,watch
容許咱們:
const state = reactive({ count: 0 })
watch(
()=>state.count,
(count,preCount)=>{
console.log('%c count的值發生修改了','color:yellow','count='+count,' preCount='+preCount)
}
)
function changeCount(){
state.count +=1
}
複製代碼
let name = ref('myy')
let age = ref(22)
watch([name,age],([name,age],[prevName,prevAge])=>{
console.log("%c --姓名和年齡更改--",'color:yellow')
console.log("%c 姓名更改",'color:green','prevName='+prevName,' name='+name )
console.log("%c 年齡更改",'color:green','prevAge='+prevAge,' age='+age )
})
function changeCount(){
name.value = 'myyyyy'
age.value +=1
}
複製代碼
setup
中定義的參數,只能在setup
的做用域下進行修改changeValue(){
console.log(this.isShowAddModal) //false
this.isShowAddModal.value =3
}
複製代碼
reactive
)在外部的method中進行修改數據 可以修改爲功
changeValue(){
console.log(this.heorData)
this.heorData.list=[]
}
//setup內部的監聽函數是否會觸發
watch(heorData,()=>{
console.log("watch:: heroData--數據修改了",heorData)
})
複製代碼
調用setup
內部暴露的函數,在setup
內部是能夠被檢測到的
ref
定義的參數,沒法在setup
外部進行參數的修改reactive
定義的參數可以進行修改,而且可以被watch
監聽到本身經過文檔+視頻+實際操做對Vue3.x有了一點點了解,有些內容其實不是不夠深刻的,比較好奇的點會經過本身想要了解的內容去實際操做一波;