目錄
一、創建Vue3工程
(一)、cli
(二)、vite
二、常用Composition API
(一)、setup函數
(二)、ref函數
(三)、reactive函數
(四)、setup注意事項
(五)、計算屬性
(六)、watch
(七)、watchEffect函數
(八)、生命周期
1、以配置項的形式使用生命周期鉤子
2、組合式api(在setup中使用)
(九)、自定義hook
(十)、toRef、toRefs
三、其他Composition API
(一)、shallowReactive、shallowRef
(二)、readonly 與 shallowReadonly
(三)、toRaw 與 markRaw
(四)、自定義ref(customRef)
(五)、provide、inject
(六)、響應式數據的判斷
五、新的組件
(一)、Fragment
(二)、Teleport
(三)、Suspense
六、Vue3的其他改變
(一)、全局API的轉移
(二)、data
(三)、過度類名更改
(四)、keyCode
(五)、移除v-on.native
(六)、移除過濾器
一、創建Vue3工程
(一)、cli
創建一個項目 | Vue CLI🛠? Vue.js 開發的標準工具https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create
##查看@vue/c1i版本,確保@vue/c1i版本在4.5.8以上
vue --version
#安裝或者升級你的@vue/cli
npm install -g @vue/cli##創建
vue create 項目名
##啟動
cd 項目名
npm run serve
(二)、vite
快速上手 | Vue.jsVue.js - 漸進式的 JavaScript 框架https://v3.cn.vuejs.org/guide/installation.html#viteVite中文網下一代前端開發與構建工具
https://vitejs.cn
##創建工程
npm init vite-app 項目名
#進入工程目錄
cd 項目名
##安裝依賴
npm i
##運行
npm run dev
二、常用Composition API
(一)、setup函數
簡單演示,下面的寫法不對,丟失了響應式。?
<template><h2>我的名字是{{ name }},年齡是{{ age }}</h2>
</template><script>
export default {name: "HelloWorld",setup() {let name = "jack";let age = 18;function sayHello() {console.log("hello");}return {name,age,sayHello,};},
};
</script>
(二)、ref函數
// 示例,執行changeInfo函數修改信息,響應式數據
import {ref} from 'vue'
export default {name: 'App',setup(){let name = ref('LHD')let age = ref(19)let job = ref({type:'前端工程師',salary:'15k'})function changeInfo(){name.value = 'DHL',age.value = '20',job.value.type = '搬磚工程師',job.value.salary = '10k'}return{name,age,job,changeInfo}}
}
(三)、reactive函數
// 先引入reactive
import {reactive} from 'vue'
// 2的示例,setup函數中改成這樣
let person = reactive({name:'LHD',age:'19',job:{type:'工程師',salary:'20k'},hobby:['Study','Video Game']
})
function changeInfo(){person.name = 'DHL',person.age = '20',person.job.type = '搬磚工程師',person.job.salary = '10k',person.hobby[1] = 'fly'
}
return{person,changeInfo
}
(四)、setup注意事項
(五)、計算屬性
(六)、watch
//情況一:監視ref定義的響應式數據
watch(sum,(newValue,oldValue)=>{console.log('sum變化了',newValue,oldValue)
},{immediate:true})//情況二:監視多個ref定義的響應式數據
watch([sum,msg],(newValue,oldValue)=>{console.log('sum或msg變化了',newValue,oldValue)
}) /* 情況三:監視reactive定義的響應式數據若watch監視的是reactive定義的響應式數據,則無法正確獲得oldValue!!若watch監視的是reactive定義的響應式數據,則強制開啟了深度監視
*/
watch(person,(newValue,oldValue)=>{console.log('person變化了',newValue,oldValue)
},{immediate:true,deep:false}) //此處的deep配置不再奏效//情況四:監視reactive定義的響應式數據中的某個屬性
watch(()=>person.job,(newValue,oldValue)=>{console.log('person的job變化了',newValue,oldValue)
},{immediate:true,deep:true}) //情況五:監視reactive定義的響應式數據中的某些屬性
watch([()=>person.job,()=>person.name],(newValue,oldValue)=>{console.log('person的job變化了',newValue,oldValue)
},{immediate:true,deep:true})//特殊情況
watch(()=>person.job,(newValue,oldValue)=>{console.log('person的job變化了',newValue,oldValue)
},{deep:true}) //此處由于監視的是reactive素定義的對象中的某個屬性,所以deep配置有效
(七)、watchEffect函數
//watchEffect所指定的回調中用到的數據只要發生變化,則直接重新執行回調。
watchEffect(()=>{const x1 = sum.valueconst x2 = person.ageconsole.log('watchEffect配置的回調執行了')
})
(八)、生命周期
1、以配置項的形式使用生命周期鉤子
與setup平級
2、組合式api(在setup中使用)
(九)、自定義hook
src/hooks/usePoint.js
///得到鼠標點的apiimport { reactive, onMounted, onBeforeUnmount } from "vue";export default function usePoint(){//響應式數據let point = reactive({x: 0,y: 0});//方法const savePoint = event => {console.log(event.pageX, event.pageY);point.x = event.pageX;point.y = event.pageY;};//生命周期onMounted(() => {window.addEventListener('click', savePoint)});onBeforeUnmount(() => {//在卸載之前取消事件的監聽window.removeEventListener('click', savePoint);});return point;
}
?src/components/Demo.vue
<template><h1>當前求和為:{{ sum }}</h1><button @click="sum++">點我加一</button><hr/><h2>當前點擊時鼠標的坐標為x:{{ point.x }}, y:{{ point.y }}</h2>
</template><script>
import {ref} from 'vue';
import usePoint from "../hooks/usePoint";
export default {name: 'Demo',setup(){let sum = ref(0);//復用自定義hooksconst point = usePoint();//返回一個對象return {sum,point}},
}
</script><style>
</style>
(十)、toRef、toRefs
<template><h4>{{ person }}</h4><h2>姓名:{{ name }}</h2><h2>年齡:{{ age }}</h2><h2>薪資:{{ salary }}K</h2><button @click="name = name + '~'">修改姓名</button><button @click="age++">增長年齡</button><button @click="salary++">增長薪資</button>
</template><script>
import { ref, reactive, toRef, toRefs} from 'vue';
export default {name: 'Demo',setup(){let person = reactive({name: '張三',age: 18,job:{j1:{salary: 20}}});//ref類型的值在模板里使用是不需要.value來取的const name1 = person.name //注意輸出字符串,并不是響應式的數據console.log('@@@@@', name1);const name2 = toRef(person,name); //RefImpl 這里的name2與person.name是完全一模一樣的(你改這里的name2與你改person.name是一碼事),且數據還是響應式的console.log('####', name2);const x = toRefs(person);console.log(x);//返回一個對象(toRef是引用 name就是person.name且為響應式)//toRef處理一個,而toRefs處理一群//大白話:toRef(s)就是方便我們把響應式數據(ref,reactive)展開丟出去,方便在模版中應用return {person,// name: toRef(person, "name"),// age: toRef(person, "age"),// salary: toRef(person.job.j1, "salary")...toRefs(person),salary: toRef(person.job.j1, 'salary') //toRef可以與toRefs連用,更加方便};//注意千萬不能這樣寫//一旦這樣寫就與元數據分離了,改name不會引起person.name的變化(因為ref把name值包裝成了一個refImpl對象)// return {// person,// name: ref(person.name),// age: ref(person.age),// salary: ref(person.job.j1.salary)// };}
}
</script><style>
</style>
三、其他Composition API
(一)、shallowReactive、shallowRef
(二)、readonly 與 shallowReadonly
(三)、toRaw 與 markRaw
<template><h2>當前求和為:{{ sum }}</h2><button @click="sum++">sum+1</button><hr/><h2>姓名:{{ name }}</h2><h2>年齡:{{ age }}</h2><h2>薪資:{{ job.j1.salary }}K</h2><h3 v-show="person.car">座駕信息:{{ person.car }}</h3><button @click="name = name + '~'">修改姓名</button><button @click="age++">增長年齡</button><button @click="job.j1.salary++">增長薪資</button><button @click="showRawPerson">輸出最原始的person</button><button @click="addCar">給人添加一臺車</button><button @click="person.car && (person.car.name +='!') ">換車名</button><button @click="changePrice">換價格</button>
</template><script>
import {markRaw, reactive, ref, toRaw, toRefs} from 'vue';export default {name: 'Demo',setup(){let sum = ref(0);let person = reactive({name: '張三',age: 18,job:{j1:{salary: 20}}});//ref reactive(響應式)const showRawPerson = () => {const p = toRaw(person);// console.log(person); //proxy代理對象 Proxy {....}p.age++; //注意此時頁面不會再發生變化了,普普通通的對象不是響應式console.log(p); //原始對象數據 {....}// const sum = toRaw(sum);// console.log(sum); //undefined //這條路走不通,toRaw只處理reactive對象}const addCar = () => {person.car = markRaw({name: 'benz',price: 40}); //在響應式的對象身上添加任何屬性都是響應式的,經過markRaw一包裝就變成最原始的數據就不會再做響應}const changePrice = () => {person.car?.price && person.car.price++;console.log(person?.car?.price);}return {sum,person,...toRefs(person),showRawPerson,addCar,changePrice};}
}
</script><style>
</style>
(四)、自定義ref(customRef)
需求
<template><input type="text" v-model="keyword"><h3>{{keyword}}</h3>
</template><script>import {ref,customRef} from 'vue'export default {name:'Demo',setup(){// let keyword = ref('hello') //使用Vue準備好的內置ref//自定義一個myReffunction myRef(value,delay){let timer//通過customRef去實現自定義return customRef((track,trigger)=>{return{get(){track() //告訴Vue這個value值是需要被“追蹤”的return value},set(newValue){clearTimeout(timer)timer = setTimeout(()=>{value = newValuetrigger() //告訴Vue去更新界面},delay)}}})}let keyword = myRef('hello',500) //使用程序員自定義的refreturn {keyword}}}
</script>
(五)、provide、inject
(六)、響應式數據的判斷
- isRef: 檢查一個值是否為一個 ref 對象
- isReactive: 檢查一個對象是否是由 reactive 創建的響應式代理
- isReadonly: 檢查一個對象是否是由 readonly 創建的只讀代理
- isProxy: 檢查一個對象是否是由 reactive 或者 readonly 方法創建的代理
五、新的組件
(一)、Fragment
- 在Vue2中: 組件必須有一個根標簽
- 在Vue3中: 組件可以沒有根標簽, 內部會將多個標簽包含在一個Fragment虛擬元素中
- 好處: 減少標簽層級, 減小內存占用
(二)、Teleport
什么是Teleport?——?Teleport
?是一種能夠將我們的組件html結構移動到指定位置的技術。
(三)、Suspense
六、Vue3的其他改變
(一)、全局API的轉移
Vue 2.x 有許多全局 API 和配置。
-
例如:注冊全局組件、注冊全局指令等
//注冊全局組件
Vue.component('MyButton', {data: () => ({count: 0}),template: '<button @click="count++">Clicked {{ count }} times.</button>'
})//注冊全局指令
Vue.directive('focus', {inserted: el => el.focus()
}
Vue3.0中對這些API做出了調整:
-
將全局的API,即:
Vue.xxx
調整到應用實例(app
)上
(二)、data
data選項應始終被聲明為一個函數。
(三)、過度類名更改
Vue2.x寫法
.v-enter,
.v-leave-to {opacity: 0;
}
.v-leave,
.v-enter-to {opacity: 1;
}
Vue3.x寫法
.v-enter-from,
.v-leave-to {opacity: 0;
}.v-leave-from,
.v-enter-to {opacity: 1;
}
(四)、keyCode
移除?keyCode作為 v-on 的修飾符,同時也不再支持config.keyCodes
(五)、移除v-on.native
移除?v-on.native
修飾符
父組件中綁定事件
<my-componentv-on:close="handleComponentEvent"v-on:click="handleNativeClickEvent"
/>
子組件中聲明自定義事件
<script>export default {emits: ['close']}
</script>