Vue概念理解
構建用戶界面:將一個個數(shù)據(jù)變成頁面展現(xiàn)出來給用戶看。
組件化模式開發(fā):將一個完整頁面分割成幾個大小不一的板塊進行遍寫開發(fā)辫诅,進行了板塊分離后,板塊將會被封裝成一個盒子涧狮,互不影響炕矮。
板塊還可以復用,一個.vue文件就是一個組件者冤,一個組件包含三要素HTML的template模板肤视,樣式表css,腳本Js涉枫。
漸進式框架:按需引入邢滑,從小到大、從易到難愿汰。
命令式編程:被動(代碼自上而下一步步按死規(guī)矩困后、按順序執(zhí)行,純js)
聲明式編程:主動衬廷、靈活(代碼不需要按順序執(zhí)行)
比如老師渴了要喝水的例子摇予。
命令式(老師吩咐你執(zhí)行,你處于被動):“老師渴了泵督,xxx同學趾盐,你先站起來,凳子往后挪一下小腊,把講臺上的水杯拿去開水間救鲤,給老師裝滿水,然后把茶葉燙一下秩冈,再泡本缠。”
聲明式(主動遞水):“老師你喝水入问!”
虛擬dom理解:其實就是三個環(huán)節(jié)丹锹,數(shù)據(jù)---虛擬dom---真實頁面,直接將虛擬dom這個環(huán)節(jié)看成一個數(shù)據(jù)的中轉緩存站或者是一個橋梁芬失,將拿到的數(shù)據(jù)先經(jīng)過虛擬dom進行第一輪的加工楣黍,加工過后,虛擬dom的數(shù)據(jù)就變成真正的dom棱烂,然后就可以進行頁面的渲染租漂,顯示界面。
diff算法:差異對比算法,當數(shù)據(jù)發(fā)生變化時哩治,vue是這樣更新節(jié)點的秃踩,找到要更新的數(shù)據(jù)進行對應更新,計算出虛擬dom中被改變的部分,然后針對該部分進行原生DOM操作,而不用重新渲染整個頁面业筏。
vue的cdn版本引入:
- 開發(fā)版本:有報錯提示信息憔杨,編寫代碼的時候用,vue.js未經(jīng)過壓縮蒜胖。
- 生產(chǎn)版本:沒有報錯提示消别,是項目上線的時候采用,vue.min.js經(jīng)過壓縮台谢。
將 Vue 應用掛載到一個 DOM 元素上(綁定容器)妖啥。
傳統(tǒng)方式:
vue3.0的寫法:先創(chuàng)建vue應用,然后掛載到跟節(jié)點上作為渲染的起點对碌。
<div id="app">
{{ message }}
</div>
const App = {
data() {
return {
message: 'Hello Vue!!'
}
}
}
Vue.createApp(App).mount('#app') //關聯(lián)容器
data 選項是一個函數(shù)荆虱,返回一個對象,Vue 在創(chuàng)建新組件實例的過程中調用此函數(shù)朽们。
computed對比methods
- computed 依賴緩存怀读、重新取值
- methods 重新渲染、重新調用
可以使用 methods 來替代 computed骑脱,效果上兩個都是一樣的菜枷,但是 computed 是基于它的依賴緩存,只有相關依賴發(fā)生改變時才會重新取值叁丧。而使用 methods 啤誊,在重新渲染的時候,函數(shù)總會重新調用執(zhí)行拥娄。
監(jiān)聽屬性 watch
watch 來查看data函數(shù)當中響應數(shù)據(jù)的變化蚊锹。
全局配置: Vue.config.productionTip 阻止 vue 在啟動時生成生產(chǎn)提示
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<title></title>
</head>
<body>
<script type="text/javascript">
Vue.config.productionTip = false
</script>
</body>
</html>
一個容器只能對應一個vue實例,當多個同名容器對應一個實例稚瘾,Vue默認是自上而下執(zhí)行牡昆,只會在第一個容器生效。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- 引入vue3.0 -->
<script src="https://unpkg.com/vue@next"></script>
<title></title>
</head>
<body>
<!-- 容器1 -->
<div id="app">
{{ message }}
</div>
<!-- 容器2 -->
<div id="app">
{{ message }}
</div>
<!-- 容器3 -->
<div id="app">
{{ message }}
</div>
<script type="text/javascript">
const App = {
data() {
return {
message: 'Hello Vue!!'
}
}
}
Vue.createApp(App).mount('#app')
</script>
</body>
</html>
多個vue實例對應同一個容器的情形摊欠,也只會在最先定義的容器生效:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- 引入vue3.0 -->
<script src="https://unpkg.com/vue@next"></script>
<title></title>
</head>
<body>
<!-- 容器1 -->
<div id="app">
{{ message }} {{message1}} {{message2}}
</div>
<script type="text/javascript">
const App = {
data() {
return {
message: 'Hello Vue!!'
}
}
}
Vue.createApp(App).mount('#app')
const App1 = {
data() {
return {
message1: 'this is a nice day'
}
}
}
Vue.createApp(App1).mount('#app')
const App2 = {
data() {
return {
message2: 'beautiful day!'
}
}
}
Vue.createApp(App2).mount('#app')
</script>
</body>
</html>
所以vue實例和容器只能是一對一的關系丢烘。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- 引入vue3.0 -->
<script src="https://unpkg.com/vue@next"></script>
<title></title>
</head>
<body>
<!-- 容器1 -->
<div id="app">
{{ message }}
</div>
<!-- 容器1 -->
<div id="app2">
{{message1}}
</div>
<!-- 容器1 -->
<div id="app3">
{{message2}}
</div>
<script type="text/javascript">
const App = {
data() {
return {
message: 'Hello Vue!!'
}
}
}
Vue.createApp(App).mount('#app')
const App1 = {
data() {
return {
message1: 'this is a nice day'
}
}
}
Vue.createApp(App1).mount('#app2')
const App2 = {
data() {
return {
message2: 'beautiful day!'
}
}
}
Vue.createApp(App2).mount('#app3')
</script>
</body>
</html>
vue的胡子語法:即使未經(jīng)data函數(shù)定義數(shù)據(jù),{{}}雙大括號里是支持js表達式和運算符的些椒。
<div id="app">
{{1+1}}
{{10*2}}
{{Date.now()}}
{{message.toUpperCase()}}
{{a?'true':'false'}}
</div>
<script type="text/javascript">
const App = {
data() {
return {
message: 'Hello Vue!!'
}
}
}
Vue.createApp(App).mount('#app')
插值語法和指令語法
- 插值語法就是雙大括號播瞳,用于讀取data中定義的數(shù)據(jù)。
- 指令語法就是v-開頭的免糕,比如v-bind
單向數(shù)據(jù)綁定和雙向數(shù)據(jù)綁定
v-bind 單向數(shù)據(jù)綁定:當頁面進行修改值時赢乓,并不會直接影響data中的數(shù)據(jù)痒给,數(shù)據(jù)是寫死的 (數(shù)據(jù)只能單向地從data流向頁面)。
v-model 雙向數(shù)據(jù)綁定:當頁面進行修改值時骏全,data中定義的數(shù)據(jù)也會隨之更新,值得注意的是尼斧,v-model只針對表單元素使用姜贡,其他標簽使用會報錯。(數(shù)據(jù)不僅能從data流向頁面棺棵,還可以從頁面回流到data當中楼咳。)
<div id="app">
<input type="text" :value="message">
<input type="text" v-model="message">
<input type="text" v-model:value="message">
<span v-model="message"></span>
</div>
<script type="text/javascript">
const App = {
data() {
return {
message: 'Hello Vue!!',
}
}
}
Vue.createApp(App).mount('#app')
</script>
因為v-model默認收集value值,所以v-model等價于v-model:value烛恤,也就是一個語法糖母怜。
v-model實現(xiàn)原理:
vue 雙向數(shù)據(jù)綁定是通過 數(shù)據(jù)劫持 結合 發(fā)布訂閱模式的方式來實現(xiàn)的, 也就是說數(shù)據(jù)和視圖同步缚柏,數(shù)據(jù)發(fā)生變化苹熏,視圖跟著變化,視圖變化币喧,數(shù)據(jù)也隨之發(fā)生改變轨域。
vue中獲取dom元素是經(jīng)過$ref綁定獲取:
給元素添加ref屬性 通過this.$refs.domName獲取
key的作用:
key作為列表循環(huán)的唯一標識杀餐,作用主要應用了diff算法來高效的更新虛擬DOM干发。
路由懶加載和圖片懶加載:
核心:按需加載
圖片懶加載:鼠標滾輪滾到底部某個位置再加載出圖片,而不是一開始就把所以圖片加載出來呈現(xiàn)史翘,那樣會導致頁面加載緩慢枉长,卡頓。提高頁面加載速度琼讽,不在可視區(qū)域內的圖片先不加載必峰,只有滾動到可視區(qū)域的時候才加載。
路由懶加載:鼠標點擊的時候才加載跳轉到某個位置钻蹬,不點擊就不加載該組件自点,避免頁面一開始就加載所有的。 當頁面很多脉让,組件很多的時候桂敛,SPA頁面在首次加載的時候,就會變的很慢溅潜。這是因為vue首次加載的時候把可能一開始看不見的組件也一次加載了术唬,這個時候就需要對頁面進行優(yōu)化,就需要異步組件了滚澜。
vue路由的2種方式:hash模式和H5的history模式
- hash模式的url帶#號
- history模式是我們正炒植郑看到url地址,history模式利用了 pushState() 和 replaceState() 方法(其中 replaceState() 方法是不能回退網(wǎng)頁的),瀏覽器的歷史記錄棧: back()借浊、forward()塘淑、go()
$route和$router的區(qū)別:
- $router為VueRouter的實例對象,里面有很多路由器對象蚂斤,指向整個大的路由對象存捺。
- $route相當于當前正在跳轉的路由對象,指向我們當前映射配置中處于活躍狀態(tài)的路由曙蒸。
v-show和v-if的區(qū)別:
- v-show指令: 控制css的display隱藏屬性變?yōu)閚one捌治,只會編譯?次;
- v-if指令: 是動態(tài)的向DOM樹內添加或者刪除DOM元素纽窟,不停的銷毀和創(chuàng)建?較消耗性能肖油。
- 如果某個場景下需要頻繁點擊則考慮使用v-show
常見的組件傳值方式有哪些?
- 父子組件之間的通訊傳值
- 兄弟組件傳值
- 復雜組件之間的傳值臂港,Vuex狀態(tài)管理
父子組件之間的通訊傳值是如何實現(xiàn)的森枪?
父傳子:父組件先通過v-bind指令進行自定義屬性的綁定,子組件在data函數(shù)中使用props選項進行接收父組件傳過來的屬性审孽。
父組件:
<template>
<view>
父組件
<test :poetry="poetry"></test>
</view>
</template>
<script>
import test from '../../components/test.vue'
export default {
data () {
return {
poetry:'昨夜星辰昨夜風,畫樓西畔桂堂東疲恢。'
}
},
methods: {
},
components:{
test
}
}
</script>
子組件:
<template>
<view>
子組件:{{poetry}}
</view>
</template>
<script>
export default {
props:['poetry'],
data () {
return {
}
}
}
</script>
子傳父:
子組件先綁定@click事件,然后在子組件的methods定義該函數(shù)瓷胧,
在該函數(shù)里頭通過$emit()觸發(fā)自定義事件(第一個參數(shù)的事件名显拳,第二個參數(shù)是攜帶參數(shù)),
父組件通過@綁定子組件通過$emit()傳遞過來的事件名搓萧,然后自己再重新定義一個新的事件名杂数,在父組件的methods里使用傳遞過來的參數(shù)。
--------------------------------------------------------------------------------------------------------------------------------
以下也是一種理解方式:
子組件想要給父組件傳值瘸洛,需要綁定事件處理函數(shù)揍移,
然后使用$emit()進行觸發(fā)通知,告訴父組件反肋,我要發(fā)送數(shù)據(jù)了那伐,記得簽收,
$emit()接受2個參數(shù)石蔗,第一個參數(shù):事件處理函數(shù)的事件名稱罕邀,第二個參數(shù):傳遞的數(shù)據(jù)。
父組件想要接收子組件的傳過來的值养距,需要在注冊的子組件上通過@符
綁定在子組件$emit()里面事件處理函數(shù)的名稱诉探,然后再命一個新的事件處理函數(shù)。
在methods定義棍厌,再使用形參來接收肾胯。
把子組件傳遞過來的數(shù)據(jù)做一個保存竖席,然后渲染在視圖層上。
子組件:
<template>
<view>
子組件:
<button type="default" @tap="sendInfo()">發(fā)送信息</button>
</view>
</template>
<script>
export default {
data () {
return {
title: '今天天氣不錯敬肚!'
}
},
methods:{
sendInfo:function(){
this.$emit('send',this.title)
}
}
}
</script>
父組件:
<template>
<view>
父組件:{{showTitle}}
<test @send="getInfo"></test>
<!-- <test @send="getInfo()"></test> 多了小括號是undefined -->
</view>
</template>
<script>
import test from '../../components/test.vue'
export default {
data () {
return {
showTitle:''
}
},
methods: {
getInfo:function(title){
console.log(title)
this.showTitle = title
}
},
components:{
test
}
}
</script>
vue-router路由使用
<router-link></router-link> 標簽相當于<a></a>毕荐,用于跳轉,<router-link to="/home">
當中的to屬性是進行導航跳轉艳馒,相當于a標簽的href路徑指定
動態(tài)綁定to屬性:<router-link :to="/home">
如果在其他標簽上使用導航跳轉憎亚,只需如此打個tag標簽:<router-link to="/home" tag="li"> </router-link>
<router-view></router-view>標簽 將顯示與 url 對應的組件,可以把它放在任何地方鹰溜,純屬就是個擺位置用的,以適應你的布局丁恭。