Vue3啟程

vue3官網(wǎng):https://v3.cn.vuejs.org/guide/introduction.html

1. 初始Vue3

導(dǎo)入vue3
<script src="https://unpkg.com/vue@next"></script>

vue3創(chuàng)建一個(gè)vue實(shí)例
在vue3里面Vue是一個(gè)對(duì)象,通過(guò)該對(duì)象的createApp()方法,創(chuàng)建一個(gè)Vue實(shí)例

 Vue.createApp({
            // 注意:vue3中,取消了el選項(xiàng)
            // el:'#app',
            // 注意:vue3中,無(wú)論是組件和是vue實(shí)例,data選項(xiàng)都必須是一個(gè)方法,由方法返回對(duì)象。
            data(){
                return {
                    name:'Vue3',
                    age:'2'
                }
            }
        }).mount('#app')

在vue2里面的Vue是一個(gè)構(gòu)造函數(shù),通過(guò)該構(gòu)造函數(shù)創(chuàng)建一個(gè)Vue實(shí)例

 new Vue({
            // el:'#app',
            // 在vue2中,data選項(xiàng)可以是對(duì)象,也可以是方法返回一個(gè)對(duì)象
            data:{
                name:'Vue2',
                age:'6'
            }
        }).$mount('#app') 

在vue2可以通過(guò)el選項(xiàng)指定一個(gè)掛載的容器,也可以通過(guò)$mount()方法指定掛載的容器
在vue3中,創(chuàng)建完一個(gè)組件實(shí)例,我們需要調(diào)用mount()方法將組件實(shí)例掛載到頁(yè)面中

2. Vue2和Vue3的響應(yīng)式

在Vue2中,Vue實(shí)例在初始化的時(shí)候,會(huì)將obj對(duì)象身上的所有數(shù)據(jù)做響應(yīng)式處理。所謂響應(yīng)式,指的是數(shù)據(jù)發(fā)生變化后,頁(yè)面自動(dòng)更新。
Vue2的響應(yīng)式:不能直接給對(duì)象添加屬性,刪除對(duì)象的屬性,不能直接操作數(shù)組的下標(biāo),但是,Vue2同時(shí)也提供了解決這些問(wèn)題的方案。

 <div id="app" v-cloak>
        <div>學(xué)生信息:{{student}}</div>
        <button @click="student.name+='!'">修改學(xué)生姓名</button>
        <button @click="student.age++">修改學(xué)生年齡</button>
        <button @click="addSex">添加性別</button>
        <button @click="delName">刪除姓名</button>
        <div>食物:{{foods}}</div>
        <button @click="addFood">添加食物</button>
        <button @click="delFood">刪除帝王蟹</button>
    </div>
// vue2的響應(yīng)式
        new Vue({
            el:'#app',
            data:{
                student:{
                    name:'張三',
                    age:20
                },
                foods:['魚(yú)翅','松茸','魚(yú)子醬','帝王蟹','熊掌']
            },
            methods: {
                //添加性別
                addSex(){
                    //后添加的屬性是非響應(yīng)式的
                    // this.student.sex='男'
                    //可以通過(guò)$forceUpdate()強(qiáng)制頁(yè)面更新一次
                    // this.$forceUpdate()

                    //推薦使用$set方法給對(duì)象添加新的屬性,確保新添加的屬性同樣具備響應(yīng)式
                    this.$set(this.student,'sex','男')
                },
                //刪除姓名
                delName(){
                    // 直接使用delete方式刪除對(duì)象的屬性后,不具備響應(yīng)式
                    // delete this.student.name
                    //使用$delete方法,刪除對(duì)象的屬性后,繼續(xù)具備響應(yīng)式
                    this.$delete(this.student,'name')
                },
                //添加食物
                addFood(){
                    // 操作數(shù)組后同時(shí)要具有響應(yīng)式,必須要使用下面的方法:
                    // push pop unshift shift sort reverse splice
                    // this.foods.push('佛跳墻')
                    // this.foods[5] = '佛跳墻'
                    // this.$forceUpdate()
                    //推薦使用$set方法根據(jù)下標(biāo)添加數(shù)組元素,確保新添加的元素同樣具備響應(yīng)式
                    this.$set(this.foods,5,'佛跳墻')
                },
                //刪除食物
                delFood(){
                    // this.foods.splice(3,1)
                    //直接根據(jù)下標(biāo)刪除數(shù)組元素,不具備響應(yīng)式
                    // this.foods[3] = null

                    //使用$delete方法,刪除數(shù)組中指定位置的元素,繼續(xù)具備響應(yīng)式
                    this.$delete(this.foods,3)
                }
            },
        }) 

vue3修復(fù)了vue2中響應(yīng)式的所有缺陷。在Vue3中,直接給對(duì)象添加屬性、直接刪除對(duì)象的屬性、根據(jù)下標(biāo)操作數(shù)組,都依然具備響應(yīng)式。

Vue.createApp({
            data() {
                return {
                    student:{
                        name:'張三',
                        age:20
                    },
                    foods:['魚(yú)翅','松茸','魚(yú)子醬','帝王蟹','熊掌']
                }
            },
            methods: {
                addSex(){
                    this.student.sex = '男'
                },
                delName(){
                    delete this.student.name
                },
                addFood(){
                    this.foods[5] = '佛跳墻'
                },
                delFood(){
                    delete this.foods[3]
                }
            },
        }).mount("#app")

3. Vue2和Vue3的響應(yīng)式原理

Vue2在實(shí)例化時(shí),會(huì)將data里面的所有數(shù)據(jù)采用 Object.defineProperty 進(jìn)行處理,從而實(shí)現(xiàn)響應(yīng)式功能。但是你之后往data里面添加的數(shù)據(jù),由于沒(méi)有采用 Object.defineProperty 進(jìn)行處理,所以不具備響應(yīng)式。$set()方法,內(nèi)部就是對(duì)單個(gè)屬性重新采用 Object.defineProperty 進(jìn)行處理,從而具備響應(yīng)式。

<h2 id="name"></h2>
<h2 id="age"></h2>
// Vue2的響應(yīng)式原理:
// 這里的obj是源對(duì)象
let obj = {
    name:'張三',
    age:20
}
// 在頁(yè)面中顯示姓名和年齡
document.getElementById('name').innerText = obj.name
document.getElementById('age').innerText = obj.age
// 這里的obj2代理對(duì)象---由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是源對(duì)象
let obj = {
    name:'張三',
    age:20
}
// 在頁(yè)面中顯示姓名和年齡
document.getElementById('name').innerText = obj.name
document.getElementById('age').innerText = obj.age
// 這里的obj2代理對(duì)象---由obj2代理obj
// new Proxy(源對(duì)象,{...})的方式,創(chuàng)建代理對(duì)象
let obj2 = new Proxy(obj,{
    //讀取屬性,參數(shù)分別是:源對(duì)象,屬性名
    get(target, property){
        // 直接根據(jù)源對(duì)象返回源對(duì)象身上的屬性
        // return target[property]
        // 通過(guò)發(fā)射對(duì)象,發(fā)射輸出源對(duì)象身上的屬性
        return Reflect.get(target,property)
    },
    //設(shè)置屬性,參數(shù)分別是:源對(duì)象,屬性名,屬性值
    set(target, property,value){
        // target[property] = value
        if(Reflect.has(target,property)){
            Reflect.set(target, property,value)
            document.getElementById(`${property}`).innerText = value
        }
    },
    //刪除屬性,參數(shù)分別是:源對(duì)象,屬性名
    deleteProperty(target, property){
        // delete target[property]
        Reflect.deleteProperty(target, property)
    }
})

4. 引出Vue3新推出的組合式API

什么是組合式API(Composition API),就是Vue推出的一些新的方法,這個(gè)方法在setup中使用
setup方法是所有組合式API的入口
Vue3中,無(wú)論是Vue實(shí)例,還是組件,data選項(xiàng)都必須是一個(gè)方法。
我們之前習(xí)慣將所有的數(shù)據(jù)放在data選項(xiàng)中定義,所有的方法放在methods選項(xiàng)中定義,
所有的計(jì)算屬性放在computed選項(xiàng)中定義,所有的偵聽(tīng)器放在watch選項(xiàng)中定義,
這樣就會(huì)導(dǎo)致一個(gè)業(yè)務(wù)的代碼會(huì)拆分到多個(gè)結(jié)構(gòu)中去寫(xiě),如果一個(gè)頁(yè)面中要操作很多個(gè)業(yè)務(wù),代碼后期維護(hù)成本會(huì)很高。
所以,Vue3引入了組合式API,簡(jiǎn)化之前繁瑣的過(guò)程,將相同業(yè)務(wù)的代碼靠在一起寫(xiě)。

 // 組合式api的作用是:將原來(lái)分散開(kāi)來(lái)定義的數(shù)據(jù),方法,計(jì)算屬性,監(jiān)聽(tīng)器,組合起來(lái)定義一個(gè)完整的業(yè)務(wù)。
 // ref用于定義響應(yīng)式數(shù)據(jù)
        let {ref} = Vue

        Vue.createApp({
            // setup是組合式api的舞臺(tái),所有的組合式api都要在setup里面使用
            setup() {
                // 在setup中,直接定義的數(shù)據(jù)是不具備響應(yīng)式的,
                // 如果要使數(shù)據(jù)具備響應(yīng)式,需要使用ref組合式API對(duì)數(shù)據(jù)進(jìn)行包裝,包裝后返回的是ref對(duì)象
                //定義汽車(chē)相關(guān)數(shù)據(jù)
                // 使用ref()方法,定義一個(gè)響應(yīng)式對(duì)象
                let carName=ref('保時(shí)捷')
                let carPrice=ref('100W')
                //定義汽車(chē)相關(guān)方法
                function updateCar(){
                    //修改對(duì)象的值,要通過(guò)value屬性
                    carName.value = '特斯拉'
                    carPrice.value = '80W'
                }
                //定義飛機(jī)相關(guān)數(shù)據(jù)
                let planeName=ref('波音747')
                let planePrice=ref('10Y')
                //定義飛機(jī)相關(guān)方法
                function updatePlane(){
                    planeName.value = 'B52轟炸機(jī)',
                    planePrice.value = '30Y'
                }
                //手表
                let watchName=ref('勞力士')
                let watchPrice=ref('10W')
                function updateWacth(){
                    watchName.value = '歐米伽',
                    watchPrice.value = '4W'
                }
                //手機(jī)
                let phoneName=ref('iphone13')
                let phonePrice=ref('5999')
                function updatePhone(){
                    phoneName.value = '華為',
                    phonePrice.value = '6999'
                }
                return{
                    //返回汽車(chē)相關(guān)數(shù)據(jù)
                    carName,
                    carPrice,
                    updateCar,
                    //返回飛機(jī)相關(guān)數(shù)據(jù)
                    planeName,
                    planePrice,
                    updatePlane,
                    //返回手表相關(guān)數(shù)據(jù)
                    watchName,
                    watchPrice,
                    updateWacth,
                    //返回手機(jī)相關(guān)數(shù)據(jù)
                    phoneName,
                    phonePrice,
                    updatePhone
                }
            },
 }).mount('#app')

5. ref和reactive

ref 和 reactive 都是用于定義響應(yīng)式數(shù)據(jù)。通常情況下,基本類(lèi)型的數(shù)據(jù),選擇用ref定義;引用類(lèi)型的數(shù)據(jù),選擇用reactive定義。
ref方法:返回的是ref對(duì)象,ref對(duì)象的value屬性是一個(gè)代理對(duì)象(Proxy)。使用ref既可以定義基本類(lèi)型數(shù)據(jù),也可以定義引用類(lèi)型數(shù)據(jù)。注意:修改ref對(duì)象的值,必須要先.value再.具體的屬性。
reactive方法:直接返回一個(gè)代理對(duì)象(Proxy)。reactive只能定義引用類(lèi)型數(shù)據(jù).

<div id="app">
    <h4>姓名:{{name}}</h4>
    <h4>學(xué)生:{{stu}}</h4>
    <button @click="updateName">修改姓名</button>
    <button @click="updateStu">修改學(xué)生</button>
</div>
let {ref,reactive} = Vue
Vue.createApp({
    setup() {
        let name = ref('張三')
        let updateName = ()=>{
            name.value = '張杰'
        }
        /* let stu = ref({
            name:'李四',
            age:20
        })
        let updateStu = ()=>{
            // 注意:修改ref對(duì)象的值,每次都要先點(diǎn)value
            stu.value.name = '李明'
            stu.value.age = 30
        } */
        // reactive組合式API方法,根據(jù)源對(duì)象返回一個(gè)代理對(duì)象(Proxy對(duì)象)
        let stu = reactive({
            name:'李四',
            age:20
        })
        let updateStu = ()=>{
            // Proxy對(duì)象,不需要先點(diǎn)value
            stu.name = '李明'
            stu.age = 30
        }
        return {
            name,
            updateName,
            stu,
            updateStu
        }
    }
}).mount('#app')
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容