Vue3啟程
關(guān)鍵字:創(chuàng)建vue實例龄捡、響應(yīng)式、響應(yīng)式原理慷暂、組合式API
1. 初始Vue3
Vue2存在一些缺陷聘殖,Vue3解決了這些缺陷,剔除了過濾器行瑞,保留了絕大部分的功能奸腺,可以說更加好用,更加豐富血久。
我們將Vue2和Vue3對比一下突照,就很直觀了:
<div id="app">
<h2>姓名:{{name}}</h2>
<h2>年齡:{{age}}</h2>
<button @click="updateData">修改數(shù)據(jù)</button>
</div>
Vue2中--創(chuàng)建實例的方式
new Vue({
//指定掛載容器
// el:'#app',
//定義屬性
data() {
return {
name:'張三',
age:20
}
},
//定義方法
methods: {
updateData(){
this.name = '李四'
this.age = 25
}
},
}).$mount('#app') //指定當(dāng)前vue實例掛載的容器
Vue3中--創(chuàng)建實例的方式
// Vue3中--創(chuàng)建實例的方式
Vue.createApp({
//注意:這個配置對象里面除了不能寫el選項,之前怎么寫氧吐,現(xiàn)在還可以怎么寫
//定義屬性
data() {
return {
name:'張三',
age:20
}
},
//定義方法
methods: {
updateData(){
this.name = '李四'
this.age = 25
}
},
}).mount('#app') //只能通過mount方法指定掛載的容器讹蘑,不用通過el選項指定
2. Vue2和Vue3的響應(yīng)式
<div id="app">
<h2>學(xué)生:{{stu}}</h2>
<h2>食物:{{foods}}</h2>
<div>
<button @click="updateStuName">修改學(xué)生姓名</button>
<button @click="addStuSex">添加學(xué)生性別</button>
<button @click="delStuAge">刪除學(xué)生年齡</button>
<button @click="updateFoods2">修改第二個食物</button>
</div>
</div>
2. Vue2和Vue3的響應(yīng)式
<div id="app">
<h2>學(xué)生:{{stu}}</h2>
<h2>食物:{{foods}}</h2>
<div>
<button @click="updateStuName">修改學(xué)生姓名</button>
<button @click="addStuSex">添加學(xué)生性別</button>
<button @click="delStuAge">刪除學(xué)生年齡</button>
<button @click="updateFoods2">修改第二個食物</button>
</div>
</div>
// Vue2
new Vue({
data() {
return {
//學(xué)生對象
stu:{
name:'張三',
age:20
},
//食物數(shù)組
foods:['榴蓮','葡萄','香蕉']
}
},
methods: {
updateStuName(){
this.stu.name = '李四'
},
addStuSex(){
// 直接給對象添加的屬性,不具備響應(yīng)式
// this.stu.sex = '男'
// 如果要給對象添加屬性筑舅,并且添加的屬性也要具備響應(yīng)式座慰,要使用$set方法
// 方法的第一個參數(shù)是指定的對象,第二個參數(shù)是屬性名翠拣,第三個參數(shù)是屬性值版仔。
this.$set(this.stu,'sex','男')
},
delStuAge(){
// 直接刪除對象身上的屬性,是不具備響應(yīng)式的
// delete this.stu.age
// 如果要刪除對象身上的屬性误墓,并且還要具備響應(yīng)式邦尊,要使用$delete方法
// 方法的第一個參數(shù)是指定的對象,第二個參數(shù)是屬性名
this.$delete(this.stu,'age')
},
updateFoods2(){
// 直接根據(jù)索引修改數(shù)組元素优烧,不具備響應(yīng)式
// this.foods[1] = '西瓜'
// 操作數(shù)組中的元素,并且還要具備響應(yīng)式链峭,只能使用數(shù)組的以下方法:
// push unshift pop shift splice reverse sort
// this.foods.splice(1,1,'西瓜')
// 如果就是想通過下標(biāo)去操作數(shù)組畦娄,還要具備響應(yīng)式,使用$set方法
this.$set(this.foods,1,'西瓜')
}
},
}).$mount('#app')
// 總結(jié)Vue2的響應(yīng)式:不能直接給對象添加屬性,刪除對象的屬性熙卡,不能直接操作數(shù)組的下標(biāo)杖刷,
// 但是,Vue2同時也提供了解決這些問題的方案驳癌。
// Vue3
Vue.createApp({
data() {
return {
//學(xué)生對象
stu:{
name:'張三',
age:20
},
//食物數(shù)組
foods:['榴蓮','葡萄','香蕉']
}
},
methods: {
updateStuName(){
this.stu.name = '李四'
},
addStuSex(){
// 在Vue3中滑燃,直接給對象添加屬性,新的屬性依然具備響應(yīng)式
this.stu.sex = '男'
},
delStuAge(){
// 在Vue3中颓鲜,直接刪除對象的屬性表窘,依然具備響應(yīng)式
delete this.stu.age
},
updateFoods2(){
// 在Vue3中,根據(jù)下標(biāo)操作數(shù)組甜滨,依然具備響應(yīng)式
this.foods[1] = '西瓜'
}
},
}).mount('#app')
// 總結(jié)Vue3的響應(yīng)式:解決了再Vue2中的所有問題乐严。
3. Vue2和Vue3的響應(yīng)式原理
<h2 id="name"></h2>
<h2 id="age"></h2>
// Vue2的響應(yīng)式原理:
// 這里的obj是源對象
let obj = {
name:'張三',
age:20
}
// 在頁面中顯示姓名和年齡
document.getElementById('name').innerText = obj.name
document.getElementById('age').innerText = obj.age
// 這里的obj2代理對象---由obj2代理obj
let obj2 = {}
// 給obj2定義name屬性
Object.defineProperty(obj2,'name',{
get(){
return obj.name
},
set(value){
obj.name = value
document.getElementById('name').innerText = obj.name
}
})
// 給obj2定義age屬性
Object.defineProperty(obj2,'age',{
get(){
return obj.age
},
set(value){
obj.age = value
document.getElementById('age').innerText = obj.age
}
})
// Vue3的響應(yīng)式原理:
// 這里的obj是源對象
let obj = {
name:'張三',
age:20
}
// 在頁面中顯示姓名和年齡
document.getElementById('name').innerText = obj.name
document.getElementById('age').innerText = obj.age
// 這里的obj2代理對象---由obj2代理obj
// new Proxy(源對象,{...})的方式,創(chuàng)建代理對象
let obj2 = new Proxy(obj,{
//讀取屬性衣摩,參數(shù)分別是:源對象昂验,屬性名
get(target, property){
// 直接根據(jù)源對象返回源對象身上的屬性
// return target[property]
// 通過發(fā)射對象,發(fā)射輸出源對象身上的屬性
return Reflect.get(target,property)
},
//設(shè)置屬性艾扮,參數(shù)分別是:源對象既琴,屬性名,屬性值
set(target, property,value){
// target[property] = value
if(Reflect.has(target,property)){
Reflect.set(target, property,value)
document.getElementById(`${property}`).innerText = value
}
},
//刪除屬性泡嘴,參數(shù)分別是:源對象甫恩,屬性名
deleteProperty(target, property){
// delete target[property]
Reflect.deleteProperty(target, property)
}
})
4. 引出Vue3新推出的組合式API
這是很棒的一個功能,和另一個R框架有點(diǎn)像磕诊,讓數(shù)據(jù)和方法在一起填物,方便維護(hù)。
<div id="app">
<div>
<h2>學(xué)生信息</h2>
<!-- 注意:ref對象在模板只不需要.value的方式獲取里面的值 -->
<h4>姓名:{{stuName}}</h4>
<h4>年齡:{{stuAge}}</h4>
<button @click="updateStu">修改學(xué)生信息</button>
</div>
<div>
<h2>汽車信息</h2>
<h4>車名:{{carName}}</h4>
<h4>車價:{{carPrice}}</h4>
<button @click="updateCar">修改汽車信息</button>
</div>
<div>
<h2>手機(jī)信息</h2>
<h4>名稱:{{phoneName}}</h4>
<h4>顏色:{{phoneColor}}</h4>
<button @click="updatePhone">修改手機(jī)信息</button>
</div>
<div>
<h2>食物信息</h2>
<h4>名稱:{{foodName}}</h4>
<h4>價格:{{foodPrice}}</h4>
<button @click="updateFood">修改食物信息</button>
</div>
</div>
什么是組合式API(Composition API)霎终,就是Vue推出的一些新的方法滞磺,這個方法在setup中使用, 從Vue身上獲取ref組合式API函數(shù)
let {ref} = Vue
Vue.createApp({
// 注意:Vue2中,Vue實例的data選項可以是一個對象莱褒,也可以是一個方法击困,由方法返回一個對象
// 但是,組件中data選項必須是一個方法广凸。
// Vue3中阅茶,無論是Vue實例,還是組件谅海,data選項都必須是一個方法脸哀。
// 我們之前習(xí)慣將所有的數(shù)據(jù)放在data選項中定義,所有的方法放在methods選項中定義扭吁,
// 所有的計算屬性放在computed選項中定義撞蜂,所有的偵聽器放在watch選項中定義盲镶,
// 這樣就會導(dǎo)致一個業(yè)務(wù)的代碼會拆分到多個結(jié)構(gòu)中去寫,如果一個頁面中要操作很多個業(yè)務(wù)蝌诡,代碼后期維護(hù)成本會很高溉贿。
// 所以,Vue3引入了組合式API浦旱,簡化之前繁瑣的過程宇色,將相同業(yè)務(wù)的代碼靠在一起寫。
/* data: function () {
return {
//定義學(xué)生數(shù)據(jù)
stuName: '張三',
stuAge: '20',
//汽車信息
carName: '奔馳',
carPrice: '50W',
//手機(jī)信息
phoneName: 'iphone',
phoneColor: '白色',
//食物信息
foodName: '漢堡',
foodPrice: '¥20'
}
},
methods: {
//修改學(xué)生的方法
updateStu(){
this.stuName = '李四'
this.stuAge = 30
},
//修改汽車的方法
updateCar(){
this.carName = '寶馬'
this.carPrice = '40W'
},
//修改手機(jī)的方法
updatePhone(){
this.phoneName = '華為'
this.phoneColor = '藍(lán)色'
},
updateFood(){
this.foodName = '蛋糕'
this.foodPrice = '¥30'
}
}, */
// setup方法是所有組合式API的入口
setup() {
// 定義學(xué)生的信息
// 在setup中颁湖,直接定義的數(shù)據(jù)是不具備響應(yīng)式的宣蠕,
// 如果要使數(shù)據(jù)具備響應(yīng)式,需要使用ref組合式API對數(shù)據(jù)進(jìn)行包裝爷狈,包裝后返回的是ref對象
let stuName = ref('張三')
let stuAge = ref('20')
let updateStu = () => {
//ref對象的value屬性保存的是值
stuName.value = '李四'
stuAge.value = 30
}
// 定義汽車的信息
let carName = ref('奔馳')
let carPrice = ref('50W')
let updateCar = () => {
carName.value = '寶馬'
carPrice.value = '40W'
}
// 定義手機(jī)的信息
let phoneName = ref('iphone')
let phoneColor = ref('白色')
let updatePhone = () => {
phoneName.value = '華為'
phoneColor.value = '藍(lán)色'
}
// 定義食物的信息
let foodName = ref('漢堡')
let foodPrice = ref('¥20')
let updateFood = () => {
foodName.value = '蛋糕'
foodPrice.value = '¥30'
}
//返回模板中需要使用的數(shù)據(jù)
return{
stuName,
stuAge,
updateStu,
carName,
carPrice,
updateCar,
phoneName,
phoneColor,
updatePhone,
foodName,
foodPrice,
updateFood
}
}
}).mount('#app')