Vue3—01.初識Vue3與Vue2的區(qū)別 / 響應(yīng)式原理 / Vue3新推出的組合式API思想

Vue.js:

漸進(jìn)式JavaScript框架官方文檔點(diǎn)我直達(dá)

漸進(jìn)式JavaScript框架

Vue它是什么

是一套用于構(gòu)建用戶界面的漸進(jìn)式框架,在使用Vue的時(shí)候,可以只使用Vue里面的一部分去配合其他前端框架一起開發(fā),也可以整個(gè)項(xiàng)目從頭到尾,從搭建項(xiàng)目,路由系統(tǒng),全局的狀態(tài)管理等全部使用Vue,非常靈活。Vue2學(xué)習(xí)資料可以看歷史文章哦

一、初識Vue3

1.引入js文件,以開發(fā)版本來學(xué)習(xí),下載到本地,首先引入Vue.js文件。

    <!-- Vue2 -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script> -->
   <!-- Vue3 -->
    <script src="https://unpkg.com/vue@next"></script>

2.Vue3創(chuàng)建一個(gè)Vue實(shí)例與Vue2創(chuàng)建一個(gè)實(shí)例的區(qū)別,在Vue3里面Vue是一個(gè)對象,通過該對象的createApp()方法,創(chuàng)建一個(gè)Vue實(shí)例,注意:在Vue3中,取消了el選項(xiàng),在Vue3中,無論論是組件和Vue實(shí)例,data選項(xiàng)都必須是一個(gè)方法,由方法返回對象。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>初識Vue3</title>
    <div id="app">
        <p>name:{{name}}</p>
        <p>age:{{age}}</p>
    </div>
</head>
<body>
    <!-- Vue2 -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script> -->
    <!-- Vue3 -->
    <script src="https://unpkg.com/vue@next"></script> 
   <script>
   //    Vue2創(chuàng)建一個(gè)Vue實(shí)例
    //    在Vue2里面的Vue是一個(gè)構(gòu)造函數(shù),通過該構(gòu)造函數(shù)創(chuàng)建一個(gè)Vue實(shí)例
    //    new Vue({
    //         //指定當(dāng)前Vue對象操作的DOM容器
    //         el:'#app',
    //         在Vue2中,data選項(xiàng)可以是對象,也可以是方法返回一個(gè)對象
    //         //定義當(dāng)前Vue對象管理的數(shù)據(jù)
    //         data:{
    //             name:'Vue2',
    //             age:'3'
    //         }.$mount('#app')
    //         Vue2可以通過el選項(xiàng)指定一個(gè)掛載的容器,也可以通過$mount()方法置頂掛載的容器
    //     })
    // Vue3創(chuàng)建一個(gè)Vue實(shí)例
    // 在Vue3里面Vue是一個(gè)對象,通過該對象的createApp()方法,創(chuàng)建一個(gè)Vue實(shí)例
      Vue.createApp({

    // 注意:在Vue3中,取消了el選項(xiàng)
    // 注意:在Vue3中,無論是組件和Vue實(shí)例,data選項(xiàng)都必須是一個(gè)方法,由方法返回對象    
          data() {
              return {
                  name:'Vue3',
                  age:2
              }
          },
      }).mount('#app')
   </script>
</body>
</html>

二、響應(yīng)式

1.Vue3修復(fù)了Vue2中響應(yīng)式的所有缺陷。什么是響應(yīng)式?當(dāng)數(shù)據(jù)變化,頁面也會隨之變化,例如Vue2的響應(yīng)式:不能直接給對象添加屬性,刪除對象的屬性,不能直接操作數(shù)組的下標(biāo),但是,Vue2同時(shí)也提供了解決這些問題的方案。

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>初識Vue2和Vue3的響應(yīng)式</title>
    <div id="app">
        <p>{{student}}</p>
        <button @click='reviseName'>修改name</button>
        <button @click='reviseAge'>修改age</button>
        <button @click='addSex'>添加sex</button>
        <button @click='delSex'>刪除sex</button>
    </div>
</head>
<body>
    <!-- Vue2 -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script> -->
    <!-- Vue3 -->
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        //    Vue2
        // new Vue({
        //     el: "#app",
        //     data: {
        //         student: {
        //             name: '萌新',
        //             age: 3
        //         }
        //     },
        //     methods: {
        //         reviseName(){
        //             this.student.name = 'Vue3'
        //         },
        //         reviseAge(){
        //             this.student.age = '30'
        //         },
        //         addSex(){
        //             // 直接給對象添加的屬性,不具備響應(yīng)式
        //             // this.student.sex = '男'
        //             // 如果要給對象添加屬性,并且添加的屬性也要具備響應(yīng)式,要使用$set方法
        //             // 方法的第一個(gè)參數(shù)是指定的對象,第二個(gè)參數(shù)是屬性名,第三個(gè)參數(shù)是屬性值。
        //             // this.$set(this.student,'sex','男')
        //             // console.log(this.student);
       //               也可以通過$forceUpdate()強(qiáng)制更新頁面一次 不推薦
       //               this.$forceUpdate()
        //         },
        //         delSex(){
        //             // 直接刪除對象身上的屬性,是不具備響應(yīng)式的
        //             // delete this.student.sex
        //              // 如果要刪除對象身上的屬性,并且還要具備響應(yīng)式,要使用$delete方法
        //              // 方法的第一個(gè)參數(shù)是指定的對象,第二個(gè)參數(shù)是屬性名
        //             //  this.$delete(this.student,'sex')
        //             //  console.log(this.student);
        //         }
        //     },
        // })
        //    Vue3
        Vue.createApp({
            data() {
                return {
                    student:{
                        name:'萌新',
                        age:3
                    }
                }
            },
            methods: {
                reviseName(){
                    this.student.name = 'Vue3'
                },
                reviseAge(){
                    this.student.age = '30'
                },
                addSex(){
                    // 在Vue3中,直接給對象添加屬性,新的屬性依然具備響應(yīng)式
                    this.student.sex = '男'
                },
                delSex(){
                    // 在Vue3中,直接刪除對象的屬性,依然具備響應(yīng)式
                    delete this.student.sex
                }
            },
        }).mount('#app')
    </script>
</body>
</html>

三、響應(yīng)式原理

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

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue2和Vue3的響應(yīng)式原理</title>
    <div id="app">
        <h2 id="name"></h2>
        <h2 id="age"></h2>
    </div>
</head>
<body>
    <!-- Vue2 -->
    <!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script> -->
    <!-- Vue3 -->
    <!-- <script src="https://unpkg.com/vue@next"></script> -->
    <script>
        // Vue2的響應(yīng)式原理:
        // 這里的obj是源對象
        let obj = {
            name: 'Vue2',
            age: 3
        }
        // 在頁面中顯示姓名和年齡
        document.getElementById('name').innerText = obj.name
        document.getElementById('age').innerText = obj.age
        // 這里的obj2代理對象---由obj2代理obj
        let obj2 = {}
        // 通過Object.defineProperty方法,給obj2添加屬性
        Object.defineProperty(obj2, 'name', {
        // 讀取屬性的值,調(diào)用get方法
            get() {
                return obj.name
            },
        // 設(shè)置屬性的值,調(diào)用set方法    
            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
            }
        }) 
        // vue2在實(shí)例化時(shí),會將data里面的所有數(shù)據(jù)采用Object.defineProperty進(jìn)行處理,實(shí)現(xiàn)實(shí)現(xiàn)響應(yīng)式功能。
        // 但是你之后往data里面添加的數(shù)據(jù),由于沒有來用 object.defineProperty進(jìn)行處理,所以不具備響應(yīng)式。
        // $set()方法,內(nèi)部就是對單個(gè)屬性重新采用 0bject.defineProperty進(jìn)行處理,從而具備響應(yīng)式。

    </script>
</body>
</html>

2.在Vue3中響應(yīng)式,無論是代碼量還是性能,Proxy更加有優(yōu)勢。

// Vue3的響應(yīng)式原理:
// 這里的obj是源對象
let obj = {
    name:'Vue3',
    age:3
}
// 在頁面中顯示姓名和年齡
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){
        // return delete target[property]
 //官方說,用這個(gè)方式發(fā)射,性能更好,更快
        Reflect.deleteProperty(target, property)
    }
})

四、引出Vue3新推出的組合式API

Vue3引入了全新的功能,叫組合式api,它是什么,可以理解為Vue新推出的一些方法,作用是:講原來分散開來定義的數(shù)據(jù),方法,計(jì)算屬性,監(jiān)聽器,組合起來定義一個(gè)完整的業(yè)務(wù),統(tǒng)一在setup中使用,在setup中,直接定義的數(shù)據(jù)是不具備響應(yīng)式的,如果要使數(shù)據(jù)具備響應(yīng)式,需要使用ref組合式API對數(shù)據(jù)進(jìn)行包裝,包裝后返回的是ref對象。

<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>車價(jià):{{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>價(jià)格:{{foodPrice}}</h4>
        <button @click="updateFood">修改食物信息</button>
    </div>
</div>
// 什么是組合式API(Composition API),就是Vue推出的一些新的方法,這個(gè)方法在setup中使用
// 從Vue身上獲取ref組合式API函數(shù)
let {ref} = Vue
Vue.createApp({
    // 注意:Vue2中,Vue實(shí)例的data選項(xiàng)可以是一個(gè)對象,也可以是一個(gè)方法,由方法返回一個(gè)對象
    // 但是,組件中data選項(xiàng)必須是一個(gè)方法。
    // Vue3中,無論是Vue實(shí)例,還是組件,data選項(xiàng)都必須是一個(gè)方法。
    // 我們之前習(xí)慣將所有的數(shù)據(jù)放在data選項(xiàng)中定義,所有的方法放在methods選項(xiàng)中定義,
    // 所有的計(jì)算屬性放在computed選項(xiàng)中定義,所有的偵聽器放在watch選項(xiàng)中定義,
    // 這樣就會導(dǎo)致一個(gè)業(yè)務(wù)的代碼會拆分到多個(gè)結(jié)構(gòu)中去寫,如果一個(gè)頁面中要操作很多個(gè)業(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')

Over

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容