Vue3——初始Vue3 & Vue2和Vue3的響應(yīng)式 & 組合式API & ref和reactive

一、初始Vue3

Vue3官方地址

1、導(dǎo)入Vue3

<script src="https://unpkg.com/vue@next"></script>

2秕脓、創(chuàng)建vue實例

Vue3和Vue2創(chuàng)建vue實例的區(qū)別:
① 在Vue3里面Vue是一個對象,通過該對象的createApp()方法,創(chuàng)建一個Vue實例悯姊。在Vue2里面的Vue是一個構(gòu)造函數(shù),通過該構(gòu)造函數(shù)創(chuàng)建一個Vue實例贩毕。
② Vue3中取消了el選項悯许,只能通過mount方法指定掛載的容器,不用通過el選項指定辉阶。Vue2可以通過el選項指定一個掛載的容器先壕,也可以通過$mount()方法指定掛載的容器。
③ Vue3中谆甜,無論是組件還是vue實例垃僚,data選項都必須是一個方法,由方法返回對象规辱。而在Vue2中谆棺,data選項可以是對象,也可以是方法返回一個對象罕袋。

<div id="app">
    <div>
        <p>name:{{name}}</p>
        <p>age:{{age}}</p>
    </div>
</div>
// vue2創(chuàng)建一個vue實例
// 在vue2里面的Vue是一個構(gòu)造函數(shù)改淑,通過該構(gòu)造函數(shù)創(chuàng)建一個Vue實例
// vue2可以通過el選項指定一個掛載的容器,也可以通過$mount()方法指定掛載的容器
/* new Vue({
    // el:'#app',
    // 在vue2中浴讯,data選項可以是對象朵夏,也可以是方法返回一個對象
    data:{
        name:'Vue2',
        age:'6'
    }
}).$mount('#app') */

// vue3創(chuàng)建一個vue實例
// 在vue3里面Vue是一個對象,通過該對象的createApp()方法榆纽,創(chuàng)建一個Vue實例
Vue.createApp({
    // 注意:這個配置對象里面除了不能寫el選項仰猖,之前怎么寫捏肢,現(xiàn)在還可以怎么寫
    // 注意:vue3中,無論是組件和是vue實例饥侵,data選項都必須是一個方法鸵赫,由方法返回對象。
    data(){
        return {
            name:'Vue3',
            age:'2'
        }
    }
}).mount('#app')

二爆捞、Vue2和Vue3的響應(yīng)式

1奉瘤、Vue2的響應(yīng)式

在Vue2中,Vue實例在初始化的時候煮甥,會將obj對象身上的所有數(shù)據(jù)做響應(yīng)式處理盗温。所謂響應(yīng)式,指的是數(shù)據(jù)發(fā)生變化后成肘,頁面自動更新卖局。
Vue2的響應(yīng)式:不能直接給對象添加屬性、刪除對象的屬性双霍,不能直接操作數(shù)組的下標(biāo)砚偶。 但是,Vue2同時也提供了解決這些問題的方案:可以通過Vue實例的$set方法洒闸,更新指定的對象屬性或數(shù)組成員染坯;$delete方法,刪除指定對象的屬性或數(shù)組的成員丘逸。

<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:['魚翅','松茸','魚子醬','帝王蟹','熊掌']
    },
    methods: {
        //添加性別
        addSex(){
            //后添加的屬性是非響應(yīng)式的
            // this.student.sex='男'
            //可以通過$forceUpdate()強制頁面更新一次
            // this.$forceUpdate()

            //推薦使用$set方法給對象添加新的屬性单鹿,確保新添加的屬性同樣具備響應(yīng)式
            this.$set(this.student,'sex','男')
        },
        //刪除姓名
        delName(){
            // 直接使用delete方式刪除對象的屬性后,不具備響應(yīng)式
            // delete this.student.name

            //使用$delete方法深纲,刪除對象的屬性后仲锄,繼續(xù)具備響應(yīng)式
            this.$delete(this.student,'name')
        },
        //添加食物
        addFood(){
            // 操作數(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)
        }
    },
})

2怀愧、Vue3的響應(yīng)式

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

<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>
// vue3的響應(yīng)式
Vue.createApp({
    data() {
        return {
            student:{
                name:'張三',
                age:20
            },
            foods:['魚翅','松茸','魚子醬','帝王蟹','熊掌']
        }
    },
    methods: {
        addSex(){
            // 在Vue3中温赔,直接給對象添加屬性蛤奢,新的屬性依然具備響應(yīng)式
            this.student.sex = '男'
        },
        delName(){
            // 在Vue3中,直接刪除對象的屬性,依然具備響應(yīng)式
            delete this.student.name
        },
        addFood(){
            // 在Vue3中啤贩,根據(jù)下標(biāo)操作數(shù)組待秃,依然具備響應(yīng)式
            this.foods[5] = '佛跳墻'
        },
        delFood(){
            delete this.foods[3]
        }
    },
}).mount("#app")

三、Vue2和Vue3的響應(yīng)式原理

1痹屹、Vue2的響應(yīng)式原理

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

<div>
    <h2 id="name"></h2>
    <h2 id="age"></h2>
    <h2 id="sex"></h2>
</div>
// vue2的響應(yīng)式原理
//源對象
let obj = {
    name:'張三',
    age:20,
    sex:'男'
}
document.querySelector('#name').innerHTML = obj.name
document.querySelector('#age').innerHTML = obj.age
document.querySelector('#sex').innerHTML = obj.sex
//定義一個obj2對象肩钠,作為obj的代理對象
let obj2 = {}

//通過Object.defineProperty方法,給obj2添加屬性
Object.defineProperty(obj2,'name',{
    //讀取屬性的值暂殖,調(diào)用get方法
    get(){
        return obj.name
    },
    //設(shè)置屬性的值价匠,調(diào)用set方法
    set(val){
        obj.name = val
        document.querySelector('#name').innerHTML = obj.name
    }
})
Object.defineProperty(obj2,'age',{
    //讀取屬性的值,調(diào)用get方法
    get(){
        return obj.age
    },
    //設(shè)置屬性的值呛每,調(diào)用set方法
    set(val){
        obj.age = val
        document.querySelector('#age').innerHTML = obj.age
    }
})
Object.defineProperty(obj2,'sex',{
    //讀取屬性的值踩窖,調(diào)用get方法
    get(){
        return obj.sex
    },
    //設(shè)置屬性的值,調(diào)用set方法
    set(val){
        obj.sex = val
        document.querySelector('#sex').innerHTML = obj.sex
    }
})

2莉给、Vue3的響應(yīng)式原理

通過new Proxy(源對象,{...})的方式毙石,創(chuàng)建代理對象。通過Proxy(代理) 攔截對象中任意屬性的變化颓遏,包括:屬性值的讀寫徐矩、屬性的添加、屬性的刪除等叁幢。
通過Reflect(反射): 對源對象的屬性進行操作滤灯。對于vue3而言,底層使用reflect會比較健壯曼玩,不容易出現(xiàn)有個錯誤就導(dǎo)致程序阻塞鳞骤。
vue3 使用proxy代理對象和Reflect反射對象組合實現(xiàn)響應(yīng)式數(shù)據(jù),在性能方面黍判,比vue2更加有優(yōu)勢豫尽。

// new Proxy()創(chuàng)建一個代理對象
let obj4 = new Proxy(obj3,{
    // 讀取屬性,參數(shù)分別是:源對象顷帖,屬性名
    get(target,property){
        // 直接返回源對象身上的指定的屬性值
        // return target[property]
        // 通過反射對象美旧,從指定的對象身上反射出指定的屬性值
        return Reflect.get(target,property)
    },
    // 設(shè)置屬性渤滞,參數(shù)分別是:源對象,屬性名榴嗅,屬性值
    set(target,property,value){
        // target[property] = value
        Reflect.set(target,property,value)
        document.querySelector(`#${property}2`).innerHTML = Reflect.get(target,property)
    },
    // 刪除屬性妄呕,參數(shù)分別是:源對象,屬性名
    deleteProperty(target,property){
        // return delete target[property]
        document.querySelector(`#${property}2`).remove()
        return Reflect.deleteProperty(target,property)
    }
})

四嗽测、Vue3新推出的組合式API

Vue3中绪励,無論是Vue實例,還是組件唠粥,data選項都必須是一個方法疏魏。我們之前習(xí)慣將所有的數(shù)據(jù)放在data選項中定義,所有的方法放在methods選項中定義厅贪,所有的計算屬性放在computed選項中定義蠢护,所有的偵聽器放在watch選項中定義。這樣就會導(dǎo)致一個業(yè)務(wù)的代碼會拆分到多個結(jié)構(gòu)中去寫养涮,如果一個頁面中要操作很多個業(yè)務(wù)葵硕,代碼后期維護成本會很高。所以贯吓,Vue3引入了組合式API懈凹,簡化之前繁瑣的過程,將相同業(yè)務(wù)的代碼靠在一起寫悄谐。
組合式API(Composition API):就是Vue推出的一些新的方法介评,這個方法在setup中使用。組合式api的作用是將原來分散開來定義的數(shù)據(jù)爬舰、方法们陆、計算屬性、監(jiān)聽器等情屹,組合起來定義一個完整的業(yè)務(wù)坪仇。
ref對象:在setup中,直接定義的數(shù)據(jù)是不具備響應(yīng)式的垃你。如果要使數(shù)據(jù)具備響應(yīng)式椅文,需要使用ref組合式API對數(shù)據(jù)進行包裝,包裝后返回的是ref對象惜颇。ref對象的value屬性保存的是值皆刺。

<div id="app">
    <div>
        <p>{{carName}}--{{carPrice}}</p>
        <button @click="updateCar">修改汽車信息</button>
    </div>
    <div>
        <p>{{planeName}}--{{planePrice}}</p>
        <button @click="updatePlane">修改飛機信息</button>
    </div>
</div>
// ref用于定義響應(yīng)式數(shù)據(jù)
let {ref} = Vue

Vue.createApp({
    // setup方法是所有組合式API的入口,所有的組合式api都要在setup里面使用
    setup() {
        //定義汽車相關(guān)數(shù)據(jù)
        // 使用ref()方法凌摄,定義一個響應(yīng)式對象
        let carName=ref('保時捷')
        let carPrice=ref('100W')
        //定義汽車相關(guān)方法
        function updateCar(){
            //修改對象的值羡蛾,要通過value屬性
            carName.value = '特斯拉'
            carPrice.value = '80W'
        }

        //定義飛機相關(guān)數(shù)據(jù)
        let planeName=ref('波音747')
        let planePrice=ref('10Y')
        //定義飛機相關(guān)方法
        function updatePlane(){
            planeName.value = 'B52轟炸機',
            planePrice.value = '30Y'
        }

        return{
            //返回汽車相關(guān)數(shù)據(jù)
            carName,
            carPrice,
            updateCar,
            //返回飛機相關(guān)數(shù)據(jù)
            planeName,
            planePrice,
            updatePlane      
        }
    },
    // vue2中只能這樣寫代碼,vue3也可以這樣寫
    /* data() {
        return {
            carName:'保時捷',
            carPrice:'100W',
            planeName:'波音747',
            planePrice:'10Y'
        }
    },
    methods: {
        updateCar(){
            this.carName = '特斯拉'
            this.carPrice = '80W'
        },
        updatePlane(){
            this.planeName = 'B52轟炸機',
            this.planePrice = '30Y'
        }
    }, */
}).mount('#app')

五锨亏、ref和reactive

refreactive 都是用于定義響應(yīng)式數(shù)據(jù)林说。通常情況下煎殷,基本類型的數(shù)據(jù),選擇用ref定義腿箩;引用類型的數(shù)據(jù),選擇用reactive定義劣摇。
ref方法:返回的是ref對象珠移,ref對象的value屬性是一個代理對象(Proxy)。使用ref既可以定義基本類型數(shù)據(jù)末融,也可以定義引用類型數(shù)據(jù)钧惧。注意:修改ref對象的值,必須要先.value再.具體的屬性勾习。
reactive方法:直接返回一個代理對象(Proxy)浓瞪。reactive只能定義引用類型數(shù)據(jù)。

<div id="app">
    <ul>
        <li>姓名:{{name}}</li>
        <li><button @click="updateName">修改姓名</button></li>
    </ul>
    <ul>
        <li>車名:{{car.name}}</li>
        <li>車價:{{car.price}}</li>
        <li><button @click="updateCar">修改汽車</button></li>
    </ul>
    <ul>
        <li>機名:{{plane.name}}</li>
        <li>機價:{{plane.price}}</li>
        <li><button @click="updatePlane">修改汽車</button></li>
    </ul>
</div>
// ref 和 reactive 用于定義響應(yīng)式數(shù)據(jù)
let {ref,reactive} = Vue
Vue.createApp({
    // 所有的組合式api巧婶,要在setup方法里面使用
    setup() {
        // 使用ref定義基本類型數(shù)據(jù)
        let name = ref('張三')
        let updateName = ()=>{
            // 修改值時乾颁,必須要點value
            name.value = '李四'
        }
        // 使用ref定義引用類型數(shù)據(jù)
        let car = ref({
            name:'奔馳',
            price:30
        })
        let updateCar = ()=>{
            // 修改值時,必須要點value
            car.value.name = '奧迪'
            car.value.price = 40
        }
        // 使用reactive定義引用類型數(shù)據(jù)
        // 注意:reactive只能定義引用類型數(shù)據(jù)
        let plane = reactive({
            name:'長城',
            price:300
        })
        let updatePlane = ()=>{
            // Proxy對象艺栈,不需要先點value
            plane.name = '東方'
            plane.price = 400
        }

        //setup方法英岭,返回出去的對象里面的成員,可以在模板中使用
        return{
            name,
            updateName,
            car,
            updateCar,
            plane,
            updatePlane
        }
    }
}).mount('#app')
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末湿右,一起剝皮案震驚了整個濱河市诅妹,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌毅人,老刑警劉巖吭狡,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異丈莺,居然都是意外死亡划煮,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門场刑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來般此,“玉大人,你說我怎么就攤上這事牵现☆戆茫” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵瞎疼,是天一觀的道長科乎。 經(jīng)常有香客問我,道長贼急,這世上最難降的妖魔是什么茅茂? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任捏萍,我火速辦了婚禮,結(jié)果婚禮上空闲,老公的妹妹穿的比我還像新娘令杈。我一直安慰自己,他們只是感情好碴倾,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布逗噩。 她就那樣靜靜地躺著,像睡著了一般跌榔。 火紅的嫁衣襯著肌膚如雪异雁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天僧须,我揣著相機與錄音纲刀,去河邊找鬼。 笑死担平,一個胖子當(dāng)著我的面吹牛示绊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播驱闷,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼耻台,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了空另?” 一聲冷哼從身側(cè)響起盆耽,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎扼菠,沒想到半個月后摄杂,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡循榆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年析恢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秧饮。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡映挂,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盗尸,到底是詐尸還是另有隱情柑船,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布泼各,位于F島的核電站鞍时,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜逆巍,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一及塘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锐极,春花似錦笙僚、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至檬嘀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間责嚷,已是汗流浹背鸳兽。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留罕拂,地道東北人揍异。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像爆班,于是被迫代替她去往敵國和親衷掷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

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