vue的核心語法
簡單入門
Vue3
向下兼容Vue2
語法,且Vue3
中的模板中可以沒有根標簽
<template><div class="person"><h2>姓名:{{name}}</h2><h2>年齡:{{age}}</h2><button @click="changeName">修改名字</button><button @click="changeAge">年齡+1</button><button @click="showTel">點我查看聯系方式</button></div>
</template><script lang="ts">export default {name:'App',data() {return {name:'張三',age:18,tel:'13888888888'}},methods:{changeName(){this.name = 'zhang-san'},changeAge(){this.age += 1},showTel(){alert(this.tel)}},}
</script>
Setup函數
在學習以下知識之前我們先了解一下 options api 和 composition api的區別: vue2中使用的是optionsAPI,來定義一個組件內部的一些屬性,如methods、data等等; 其缺點往往會在大項目中體現出來,比如一個簡單的計數器功能,可能需要在methods內部書寫一部分邏輯,在computed內部也書寫一部分邏輯,那么問題來了:如果該組件內部有n個這樣的小功能,那么此時代碼邏輯是十分分散的,并且后期迭代維護面臨的問題也是可能修改一個需求需要在不同的屬性內部反復查找相關的代碼,而compositionAPI的出現就是為了解決這一問題的。
vue3新增的compositionAPI主要就是為了解決API太過于分散的問題,避免一個功能點下的api太過于分散不便于維護,將同一個功能下的api統一放到一個地方,這樣一來項目的開發和維護就簡便多了。compositionAPI也叫做組合式API,vue3中組合式API的入口就是setup函數;
setup
是Vue3
中一個新的配置項,值是一個函數,它是 Composition API
“表演的舞臺”,組件中所用到的:數據、方法、計算屬性、監視......等等,均配置在setup
中。
特點如下:
-
setup
函數返回的對象中的內容,可直接在模板中使用。 -
setup
中訪問this
是undefined
。 -
setup
函數會在beforeCreate
之前調用,它是“領先”所有鉤子執行的。 -
普通寫法[不推薦]
通過 export default { setup(){ } } 來定義setup函數 , 這種方式不推薦
-
<template><div class="person"><h2>姓名:{{name}}</h2><h2>年齡:{{age}}</h2><button @click="changeName">修改名字</button><button @click="changeAge">年齡+1</button><button @click="showTel">點我查看聯系方式</button></div> </template><script lang="ts">export default {name:'Person',setup(){// 數據,原來寫在data中(注意:此時的name、age、tel數據都不是響應式數據)let name = '張三'let age = 18let tel = '13888888888'// 方法,原來寫在methods中function changeName(){name = 'zhang-san' //注意:此時這么修改name頁面是不變化的console.log(name)}function changeAge(){age += 1 //注意:此時這么修改age頁面是不變化的console.log(age)}function showTel(){alert(tel)}// 返回一個對象,對象中的內容,模板中可以直接使用return {name,age,tel,changeName,changeAge,showTel}}} </script>
語法糖[推薦]
-
<template><div class="person"><h2>姓名:{{name}}</h2><h2>年齡:{{age}}</h2><button @click="changName">修改名字</button><button @click="changAge">年齡+1</button><button @click="showTel">點我查看聯系方式</button></div> </template><script lang="ts">export default {name:'Person',} </script><!-- 下面的寫法是setup語法糖 --> <script setup lang="ts">console.log(this) //undefined// 數據(注意:此時的name、age、tel都不是響應式數據)let name = '張三'let age = 18let tel = '13888888888'// 方法function changName(){name = '李四'//注意:此時這么修改name頁面是不變化的}function changAge(){console.log(age)age += 1 //注意:此時這么修改age頁面是不變化的}function showTel(){alert(tel)} </script>
注意:在setup語法中使用 this 會出現unidefined , 在
setup
中你應該避免使用this
,因為它不會找到組件實例。setup
的調用發生在data
property、computed
property 或methods
被解析之前,所以它們無法在setup
中被獲取,這也是為了避免setup()和其他選項式API混淆。
數據響應函數
什么是響應式:響應式指的是,把數據綁定當視圖,當數據的值發生改變,視圖也會跟著重新渲染。
ref:基礎數據響應式函數
VUE3提供了ref函數可以在修改完 數據后自動渲染視圖,類似余雙向綁定
-
在js中通過 import {ref} from "vue"; 來聲明 ref函數
-
注意:ref屬性在js中要使用.value 取值
<template><div class="person"><h2>姓名:{{name}}</h2><h2>年齡:{{age}}</h2><button @click="changeName">修改名字</button><button @click="changeAge">年齡+1</button><button @click="showTel">點我查看聯系方式</button></div>
</template><script setup lang="ts" name="Person">import {ref} from 'vue'// name和age是一個RefImpl的實例對象,簡稱ref對象,它們的value屬性是響應式的。let name = ref('張三')let age = ref(18)// tel就是一個普通的字符串,不是響應式的let tel = '13888888888'function changeName(){// JS中操作ref對象時候需要.valuename.value = '李四'console.log(name.value)// 注意:name不是響應式的,name.value是響應式的,所以如下代碼并不會引起頁面的更新。// name = ref('zhang-san')}function changeAge(){// JS中操作ref對象時候需要.valueage.value += 1 console.log(age.value)}function showTel(){alert(tel)}
</script>
通過ref獲取dom對象
<template><input ref="inputRef" :value="refValue"/>
</template><script setup>import {ref} from "vue";//變量名 inputRef 和 dom元素上的ref="inputRef" 一樣,就能獲取到dom元素let inputRef = ref(null);console.log(inputRef);</script>
reactive創建:對象類型的響應式數據
對于對象類型可以使用reactive進行響應式函數處理
<template><div class="person"><h2>汽車信息:一臺{{ car.brand }}汽車,價值{{ car.price }}萬</h2><h2>游戲列表:</h2><ul><li v-for="g in games" :key="g.id">{{ g.name }}</li></ul><h2>測試:{{obj.a.b.c.d}}</h2><button @click="changeCarPrice">修改汽車價格</button><button @click="changeFirstGame">修改第一游戲</button><button @click="test">測試</button></div>
</template><script lang="ts" setup name="Person">
import { reactive } from 'vue'// 數據
let car = reactive({ brand: '奔馳', price: 100 })
let games = reactive([{ id: 'ahsgdyfa01', name: '英雄聯盟' },{ id: 'ahsgdyfa02', name: '王者榮耀' },{ id: 'ahsgdyfa03', name: '原神' }
])
let obj = reactive({a:{b:{c:{d:666}}}
})function changeCarPrice() {car.price += 10
}
function changeFirstGame() {games[0].name = '流星蝴蝶劍'
}
function test(){obj.a.b.c.d = 999
}
</script>
注意:其實ref
接收的數據可以是:基本類型、對象類型。若ref
接收的是對象類型,內部其實也是調用了reactive
函數
例如:
template><div class="person"><h2>汽車信息:一臺{{ car.brand }}汽車,價值{{ car.price }}萬</h2><h2>游戲列表:</h2><ul><li v-for="g in games" :key="g.id">{{ g.name }}</li></ul><h2>測試:{{obj.a.b.c.d}}</h2><button @click="changeCarPrice">修改汽車價格</button><button @click="changeFirstGame">修改第一游戲</button><button @click="test">測試</button></div>
</template><script lang="ts" setup name="Person">
import { ref } from 'vue'// 數據
let car = ref({ brand: '奔馳', price: 100 })
let games = ref([{ id: 'ahsgdyfa01', name: '英雄聯盟' },{ id: 'ahsgdyfa02', name: '王者榮耀' },{ id: 'ahsgdyfa03', name: '原神' }
])
let obj = ref({a:{b:{c:{d:666}}}
})console.log(car)function changeCarPrice() {car.value.price += 10
}
function changeFirstGame() {games.value[0].name = '流星蝴蝶劍'
}
function test(){obj.value.a.b.c.d = 999
}
</script>
對比:
-
ref
用來定義:基本類型數據、對象類型數據; -
reactive
用來定義:對象類型數據。 -
ref
創建的變量必須使用.value
-
reactive
重新分配一個新對象,會失去響應式
toRef 和 toRefs
toRef解析響應式
將一個響應式對象中的每一個屬性,轉換為ref
對象,toRefs
與toRef
功能一致,但toRefs
可以批量轉換。
<template><div class="person"><h2>姓名:{{person.name}}</h2><h2>年齡:{{person.age}}</h2><h2>性別:{{person.gender}}</h2><button @click="changeName">修改名字</button><button @click="changeAge">修改年齡</button><button @click="changeGender">修改性別</button></div>
</template><script lang="ts" setup name="Person">import {ref,reactive,toRefs,toRef} from 'vue'// 數據let person = reactive({name:'張三', age:18, gender:'男'})// 通過toRefs將person對象中的n個屬性批量取出,且依然保持響應式的能力let {name,gender} = toRefs(person)// 通過toRef將person對象中的gender屬性取出,且依然保持響應式的能力let age = toRef(person,'age')// 方法function changeName(){name.value += '~'}function changeAge(){age.value += 1}function changeGender(){gender.value = '女'}
</script>
computed計算函數
下面通過計算函數演示2個值相加,需要通過 import {computed} from "vue"; 引入函數
?
<template><div class="person">姓:<input type="text" v-model="firstName"> <br>名:<input type="text" v-model="lastName"> <br>全名:<span>{{fullName}}</span> <br><button @click="changeFullName">全名改為:li-si</button></div>
</template><script setup lang="ts" name="App">import {ref,computed} from 'vue'let firstName = ref('zhang')let lastName = ref('san')// 計算屬性——只讀取,不修改/* let fullName = computed(()=>{return firstName.value + '-' + lastName.value}) */// 計算屬性——既讀取又修改let fullName = computed({// 讀取get(){return firstName.value + '-' + lastName.value},// 修改set(val){console.log('有人修改了fullName',val)firstName.value = val.split('-')[0]lastName.value = val.split('-')[1]}})function changeFullName(){fullName.value = 'li-si'}
</script>
watch監聽器
watch的作用是用來監聽某個值的變化從而出發watch回調。watch可以:
-
監聽單體數據
-
監聽對象
-
監聽對象的某個屬性
-
監聽多個數據
?
<template><div class="watch"></div><button @click="value++">修改value</button><button @click="persion.age++">修改persion</button>
</template>
<script setup>import {reactive, ref, watch} from "vue";const value = ref(1111);
const persion = reactive({username:"zs" ,age:18
})
//監聽單個值
watch(value,()=>{console.log(value);
})
//監聽對象
watch(persion,()=>{console.log(persion);
})//監聽多個,用[]包含多個
watch([persion,value],()=>{console.log(persion,value);
});//監聽對象的屬性watch(()=>persion.age,()=>{console.log(persion);
}); </script>
watchEffect監聽副作用
立即運行一個函數,同時響應式地追蹤其依賴,并在依賴更改時重新執行該函數。watchEffect的作用是只要使用到的數據都會被監聽到,無需指定具體監聽誰,他包含4個功能
-
頁面加載,watchEffect的回調就會立即執行
-
只要watchEffect 只要里面使用了任何數據,就會觸發回到函數
-
onCleanup函數可以清除副作用
-
返回一個stopHandler可以停止監聽
?
<template><div class="watch_effect"></div><button @click="num++">num++</button><button @click="stopHandler">StopWatch</button>
</template><script setup>import {ref, watchEffect} from "vue";const num = ref(1111);//1.頁面加載,初始化立即回執行回調
//2.只要watchEffect 只要里面使用了數據,就會觸發回到函數
//3.onCleanup函數可以清除副作用
//4.返回一個stopHandler可以停止監聽
/**
watchEffect(()=>{console.log(num.value);
})**/const stopHandler = watchEffect(onCleanup=>{console.log(num.value);onCleanup(()=>{console.log("清除副作用");});
})</script>
生命周期方法
因為 setup
是圍繞 beforeCreate
和 created
生命周期鉤子運行的,所以不需要顯式地定義它們。換句話說,在這些鉤子中編寫的任何代碼都應該直接在 setup
函數中編寫。下表包含如何在 setup () 內部調用生命周期鉤子:
選項式 API(VUE2) | Hook inside setup |
---|---|
beforeCreate | Not needed* ? ?不需要 |
created | Not needed* ? ?不需要 |
beforeMount | onBeforeMount |
掛載之前 | |
mounted | onMounted |
頁面加載完成時執行 | |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
頁面銷毀時執行 | |
errorCaptured | onErrorCaptured |
renderTracked | onRenderTracked |
renderTriggered | onRenderTriggered |
activated | onActivated |
deactivated | onDeactivated |
父子組件
父傳參數給子
第一步:創建一個父組件頁面,引入子組件,并傳入參數 parent.vue
<template><H1 class="parent_child">父傳子</H1><h2>使用子組件傳參</h2><child-vue text="傳入靜態文本" :num="num" :title="title" :persion="persion"></child-vue>
</template><script setup>//引入子組件取名用駝峰,頁面用中劃線 <child-vue></child-vue>
import ChildVue from "@/views/parent_child/child.vue";
import {reactive, ref} from "vue";//構建一個響應式對象
const persion = reactive({username:"zs",age:18
})
//定義響應式變量
const title = ref("我是標題");
const num = ref(111);
</script>
?第二步:創建一個子組件頁面 : child.vue , 通過 defineProps接受父傳入的參數
<template><h2>text:{{text}}</h2><h2>num:{{num}}</h2><h2>title:{{title}}</h2><h2>persion:{{persion}}</h2>
</template><script setup>
//通過defineProps來接受父傳入過來的參數
const prop = defineProps({text:String,num:Number,title:String,persion:Object
})
//在js中可以讀取父傳入過來的參數,但是不能修改
console.log("prop.title" , prop.title)</script>
子傳參給父
子組件給父組件傳值,需要通過defineEmits在子組件聲明事件方法,然后調用該事件方法傳值,父組件需要監聽該事件方法取值。第一步:在子組件中準備一個按鈕,點擊按鈕就給父組件傳值。然后給按鈕綁定一個方法。
<h1>給父組件傳參</h1>
<button @click="sendData2Parent">給父組件傳參</button>------------------------------------------------------------------------------------------//聲明事件
const $emits = defineEmits(["data2parent","事件名","事件名"]);const sendData2Parent = ()=>{//調用聲明的事件$emits('data2parent',"傳給父組件的數據");
}
-
const $emits = defineEmits(["data2parent","事件2","事件3"]); 自定義了三個事件
-
$emits('data2parent',"傳給父組件的數據"); 調用自定義的事件
第二步:在父組件中綁定該事件,并調用一個函數來接受值
<child-vue @data2parent="getDataFromChild" ...></child-vue>const getDataFromChild = (data)=>{console.log("打印數據",data);
}
子暴露
VUE3提供了 defineExpose 來暴露子組件中的數據和方法在父組件中可以拿到子組件中暴露的數據或者方法。第一步在子組件中暴露數據
//子暴露
defineExpose({data:"我是子暴露的數據",sayHi:()=>{return "我是子暴露的方法被調用返回的結果";}
})
第二步:在父組件接受子暴露的數據
<child-vueref="childVueRef" ...></child-vue>//用一個響應式變量,接受子暴露的數據
const childVueRef = ref(null);
onMounted(()=>{console.log("子暴露的數據:",childVueRef.value.data);console.log("子暴露的方法:",childVueRef.value.sayHi());
})
-
ref="childVueRef" : 接受子暴露,把數據綁定給childVueRef
注意:因為在父組件的 setup 函數中,聲明周期很早,此時子組件還沒加載,所以需要在onMounted去調用子暴露的數據和方法才可以拿到結果。
寫在最后:Vue3是當前前端的主流框架,本篇介紹了一些vue3的基礎核心語法,希望能夠給大家帶來幫助。筆者小,中,大廠均有面試經歷,堅持每日分享java全棧開發知識,希望能夠和大家共同進步。