目錄
一、vue組件的三個API:prop、event、slot
二、Vue生命周期中的鉤子函式
三、自定義指令
四、mixins基礎概況
五、修飾符
一、vue組件的三個API:prop、event、slot
prop 定義了這個組件有哪些可配置的屬性,組件的核心功能也都是它來確定的,
組件里定義的prop都是單向資料流,只能通過父級組件對齊進行修改,組件本身不能修改props的值,只能修改定義在data里的資料,非要修改,也是通過后面介紹的自定義事件通知父級,由父級來修改;
在子組件定義prop是,使用了camelCase的命名法,由于html特性不區分大小寫,camelCase的prop用于特性時,會轉為短橫線隔開(比如availableValue)
因為陣列或物件是地址參考,vue不會檢測到props發生改變
但官方不建議在子組件內改變父組件的值,因為這違反了vue中props單向系結的思想,

solt(插槽)
<template>
<button>
<slot name="icon"></slot>
<slot></slot>
</button>
</template>
這里的節點就是指定的一個插槽的位置,這樣在組件內部就可以擴展內容了;
這樣,父級內定義的內容,就會出現在組件對應的 slot 里,沒有寫名字的,就是默認的 slot;
event(事件)
this.$emit('on-click', event);
在組件中可以通過$emit觸發自定義事件on-click,在父組件通過@on-click來監聽組件之間的通信方式
父組件向子組件的通信方式可以通過props傳遞, 子組件向父組件傳遞資料則可以通過event傳遞:
非父子組件之間的通信方式:eventBus
我是使用的通過在根組件,也就是#app組件上定義了一個所有組件都可以訪問到的組件,具體使用方式如下;
使用eventBus傳遞資料,我們一共需要做3件事情
1.給app組件添加Bus屬性 (這樣所有組件都可以通過this.$root.Bus訪問到它,而且不需要引入任何檔案);
2.在組件1里,this. emit觸發事件;
3.在組件2里,this. on監聽事件;
this.$nextTick:
在某個動作有可能改變DOM元素結構的時候,對DOM一系列的js操作都要放進Vue.nextTick()的回呼函式中,Vue 實作回應式并不是資料發生變化之后 DOM 立即變化,而是按一定的策略進行 DOM 的更新,
$nextTick 是在下次 DOM 更新回圈結束之后執行延遲回呼,在修改資料之后使用 ,
因為資料在頁面的加載是有延遲,而$nextTick是在下次DOM更新時執行,$nextTick正好符合我們的要求,
vue中本身是不支持ajax的,要想進行異步請求,則需要通過axios來進行操作,但是再使用Echarts的時候,則需要獲取所有的資料后,在進行更新圖示資料,
這是可以通過async/ await來處理異步/同步請求:
給物件賦值
由1可以引申出,地址參考型別的資料,例如物件obj ={a:1},如果想要修改obj中的a屬性,通過obj.a = 2這樣賦值,頁面不會更新,需使用vue.set方法更改才會起作用, Vue.set(this,obj,a,2) 或者 this.$set(obj,'a',2);或者this,$forceupdate()
Vue 實體的資料都保存在 data 物件中,Vue 將會遞回將 data 的屬性轉換為 getter/setter,
從而讓 data 的屬性能夠回應資料變化,

同樣,如果要給obj增加一個新屬性,如果該屬性未在data中宣告,頁面也不會重繪,也就是vue檔案中宣告的“Vue 不能檢測到物件屬性的添加或洗掉”,同樣需要使用vue.set 或者this.$set方法進行賦值才好使,
深拷貝/淺拷貝
先來看一個簡單的例子:
let obj = {name:'fiona-SUN'};
let copyObj = obj;
copyObj.name = 'fiona';
console.log(copyObj.name); // 'fiona'
console.log(obj.name); // 'fiona'
在js中也有堆疊(stack)和堆(heap)的概念:
堆疊:自動分配的記憶體空間,大小確定會自動釋放,存放變數/區域變數/形參等,在js中存放簡單資料段(五種基本資料型別:Number、String、Boolean、Null、Undefined),他們是按值存放的,可以直接訪問,
堆:動態分配的記憶體,大小不定并且不會自動釋放,存放在堆記憶體中的物件,堆疊中的變數實際保存的是一個指標,這個指標指向堆中的某一個位置,
所以上述例子中,屬于淺拷貝,當我們宣告一個物件,由于他不屬于五種基本資料型別(即非簡單資料段),堆疊中會存放一個我們宣告的obj變數,它指向了堆中實際的這個物件的地址,當我們把這個參考地址賦值給了copyObj,實際它獲得的是一個與obj一致的指向堆中的地址,當copyOjb改變了指向的物件地址的實際的值的時候,obj拿到的值也就自然而然變化了,看圖理解?

es6之展開Object.assign(拷貝obj的內容到一個新的堆記憶體,copyObj存盤新記憶體的參考)
復制一個物件
const obj = { a: 1 };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
針對深拷貝,需要使用其他辦法,因為 Object.assign()拷貝的是屬性值,假如源物件的屬性值是一個物件的參考,那么它也只指向那個參考,
let obj1 = { a: 0 , b: { c: 0}};
let obj2 = Object.assign({}, obj1);
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
obj1.a = 1;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
obj2.a = 2;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 0}}
obj2.b.c = 3;
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}}
console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}}
為大家精心準備了vue課程,微信搜索關注公眾號:【zhulin1028】,或者掃描以下二維碼,回復【vue課程】即可免費獲取,

二、Vue生命周期中的鉤子函式

1). 初始化顯示(只執行一次)
* beforeCreate()el 和 data 并未初始化
* created() 完成了 data 資料的初始化,el沒有
* beforeMount()完成了 el 和 data 初始化
* mounted()完成掛載,獲取到DOM節點
2). 更新狀態(可執行多次)
* beforeUpdate()
* updated():我們單擊頁面中的“更新資料”按鈕,將資料更新,下面就能看到data里的值被修改后,將會觸發update的操作
3). 銷毀vue實體: vm.$destory()(只執行一次)
* beforeDestory()
* destoryed()
created()/mounted(): 發送api請求, 啟動定時器等異步任務
beforeDestory(): 做收尾作業, 如: 清除定時器,音頻播放器
destoryed :銷毀完成后,我們再重新改變message的值,vue不再對此動作進行回應了,但是原先生成的dom元素還存在,可以這么理解,執行了destroy操作,后續就不再受vue控制了,因為這個Vue實體已經不存在了,
實體:
vue中的setInterval在頁面離開之后仍會執行,在切換多個路由之后,定時器的速度會越來越快
beforeDestory(){
if(this.timer){
clearInterval(this.timer)
}}
總結:用created還是mounted方法看情況,一般放到created里面就可以了,這樣可以及早發請求獲取資料,如果有依賴dom必須存在的情況,就放到mounted(){this.$nextTick(() => { /* code */ })}

ref
ref 被用來給元素或子組件注冊參考資訊的靜態節點,參考資訊將會注冊在父組件的 $refs 物件上,
如果在普通的 DOM 元素上使用,參考指向的就是 DOM 元素;如果用在子組件上,參考就指向組件,ref和$refs其實就是用來獲取/操作DOM元素的;類似于jquey中的$(".xxx");
快取問題
ref 需要在dom渲染完成后才會有,在使用的時候確保dom已經渲染完成,比如在生命周期 mounted(){} 鉤子中呼叫,或者在 this.$nextTick(()=>{}) 中呼叫,
vue中過濾器filters的使用
組件內寫法
filters:{
filter:function(data,arg1,arg2){
return ....
}
}
1.在html中使用
{{ msg | filter('arg1','arg2') }}
2.methods中使用,并傳參
methods:{
fn(){
let filter = this.$options.filters['filter']
let data = filter(this.msg,arg1,arg2)
}
}
3.在v-html中使用filters
<p><v-html="$options.filters.filter(this.msg,arg1,arg2)"></p>
Directive:指令
v-if 是“真正”的條件渲染,因為它會確保在切換程序中條件塊內的事件監聽器和子組件適當地被銷毀和重建,
v-if 也是惰性的:如果在初始渲染時條件為假,則什么也不做——直到條件第一次變為真時,才會開始渲染條件塊,
相比之下,v-show 就簡單得多——不管初始條件是什么,元素總是會被渲染,并且只是簡單地基于 CSS 進行切換,不用在效驗必選項
v-show是通過css的display:none進行隱藏控制,所以一開始就會渲染,肯定能夠取到元素
一般來說,v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷,因此,如果需要非常頻繁地切換,則使用 v-show 較好;如果在運行時條件很少改變,則使用 v-if 較好,
三、自定義指令
組件:一般是指一個獨立物體,組件之間的關系通常都是樹狀,Vue指令:用以改寫某個組件的默認行為,或者增強使其獲得額外功能,一般來說可以在同一個組件上疊加若干個指令,使其獲得多種功能,比如 v-if,它可以安裝或者卸載組件,
Vue 指令生命周期
bind:只呼叫一次,指令第一次系結到元素時呼叫,在這里可以進行一次性的初始化設定
inserted:被系結元素插入父節點時呼叫 (僅保證父節點存在,但不一定已被插入檔案中),
update:所在組件的 VNode 更新時呼叫,但是可能發生在其子 VNode 更新之前,指令的值可能發生了改變,也可能沒有,但是你可以通過比較更新前后的值來忽略不必要的模板更新 ,
componentUpdated:指令所在組件的 VNode 及其子 VNode 全部更新后呼叫,
unbind:只呼叫一次,指令與元素解綁時呼叫,
生命周期函式中的引數
el: 指令所系結的元素,可以用來直接操作 DOM,就是放置指令的那個元素,
binding: 一個物件,里面包含了幾個屬性
name:指令名,不包括 v- 前綴,
value:指令的系結值,例如:v-my-directive="1 + 1" 中,系結值為 2,
oldValue:指令系結的前一個值,僅在 update 和 componentUpdated 鉤子中可用,無論值是否改變都可用,
expression:字串形式的指令運算式,例如 v-my-directive="1 + 1" 中,運算式為 "1 + 1",
arg:傳給指令的引數,可選,例如 v-my-directive:foo 中,引數為 "foo",
modifiers:一個包含修飾符的物件,例如:v-my-directive.foo.bar 中,修飾符物件為 { foo: true, bar: true },
vnode:Vue 編譯生成的虛擬節點,
oldVnode:上一個虛擬節點,僅在 update 和 componentUpdated 鉤子中可用

<div v-demo="model">自定義指令</div>
provide 和 inject 主要為高階插件/組件庫提供用例,并不推薦直接用于應用程式代碼中,
這對選項需要一起使用,以允許一個祖先組件向其所有子孫后代注入一個依賴,不論組件層次有多深,并在起上下游關系成立的時間里始終生效,

這樣,任何頁面或組件,只要通過 inject 注入 app 后,就可以直接訪問 userInfo 的資料了,比如:

四、mixins基礎概況
vue中的解釋是這樣的,如果覺得語言枯燥的可以自行跳過嘿~
混入 (mixins): 是一種分發 Vue 組件中可復用功能的非常靈活的方式,混入物件可以包含任意組件選項,當組件使用混入物件時,所有混入物件的選項將被混入該組件本身的選項,


總結
vuex:用來做狀態管理的,里面定義的變數在每個組件中均可以使用和修改,在任一組件中修改此變數的值之后,其他組件中此變數的值也會隨之修改,
Mixins:可以定義共用的變數,在每個組件中使用,引入組件中之后,各個變數是相互獨立的,值的修改在組件中不會相互影響,
與公共組件的區別
組件:在父組件中引入組件,相當于在父組件中給出一片獨立的空間供子組件使用,然后根據props來傳值,但本質上兩者是相對獨立的,
Mixins:則是在引入組件之后與組件中的物件和方法進行合并,相當于擴展了父組件的物件與方法,可以理解為形成了一個新的組件,
利用本地化快取機制
這種通信比較簡單,缺點是資料和狀態比較混亂,不太容易維護;
通過window.localStorage.getItem(key) 獲取資料; 通過window.localStorage.setItem(key,value) 存盤資料;
注意用JSON.parse() / JSON.stringify() 做資料格式轉換;
五、修飾符
vue中的修飾符主要分為兩類:
1.事件修飾符:
.stop 阻止單機事件冒泡
.prevent 阻止默認行為(比如 @submit.prevent 會阻止提交后重繪頁面)(類似a標簽javascript:void(0))
.capture 添加事件偵聽器時使用捕獲模式
.self 只有事件在元素本身(而不是子元素)觸發時觸發回呼
.once 只觸發一次(組件也適用)
.key 觸發事件的按鍵
修飾符可以串聯

.native
現在在組件上使用 v-on 只會監聽自定義事件 (組件用 $emit 觸發的事件),如果要監聽根元素的原生事件,可以使用 .native 修飾符
就是在父組件中給子組件系結一個原生的事件,就將子組件變成了普通的HTML標簽,不加'. native'事件是無法觸 發的,
@keyup.enter.native
2.v-model 修飾符:
.lazy
在各種情況下,v-model在input事件中同步輸入框的值與資料,但你可以添加一個修飾符lazy,從而轉變為在change事件中同步:
<!-- 在 "change" 而不是 "input" 事件中更新 -->
<input v-model.lazy="msg" >
.number
如果想自動將用戶的輸入值轉換為Number型別(如果原值的轉換結果為NaN則回傳原值),可以添加一個修飾符number給v-model來處理輸入值:
<input v-model.number="age" type="number">
這通常很有用,因為在type="number"時HTML中輸入的值也總是會回傳字串型別,
.trim
如果要自動過濾用戶輸入的首尾空格,可以添加trim修飾符到v-model上過濾輸入:
插槽
除非子組件模板包含至少一個<slot>插口,否則父組件的內容將被替換,當子組件模板只有一個沒有屬性的slot時,父組件整個內容片段將插入到slot所在的DOM位置,并替換掉slot標簽本身,
最初在<slot>標簽中的任何內容都被替換為內容,備用內容在子組件的作用域內編譯,并且僅在容納元素為空,且沒有要插入的內容時才顯示備用內容,
假定my-component組件有下面模板:
<div>
<h2>我是子組件的標題</h2>
<slot>
只有在沒有要分發的內容時才會顯示,
</slot>
</div>
父組件模版:
<div>
<h1>我是父組件的標題</h1>
<my-component>
<p>這是一些初始內容</p>
<p>這是更多的初始內容</p>
</my-component>
</div>
渲染結果:
<div>
<h1>我是父組件的標題</h1>
<div>
<h2>我是子組件的標題</h2>
<p>這是一些初始內容</p>
<p>這是更多的初始內容</p>
</div>
</div>
具名插槽
<slot>可以元素用一個特殊的屬性name來配置如何配給物內容,多個槽可以有不同的名字,具名時隙匹配將內容片段中有對應slot特性的元素,
仍然可以有一個匿名slot,它是替換slot,作為找回匹配的內容片段的備用插槽,如果沒有替換的slot,這些發現匹配的內容片段將被拋棄,
例如,我們假定一個有app-layout組件,它的模板為:
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
父組件模版:
<app-layout>
<h1 slot="header">這里可能是一個頁面標題</h1>
<p>主要內容的一個段落,</p>
<p>另一個主要段落,</p>
<p slot="footer">這里有一些聯系資訊</p>
</app-layout>
渲染結果為:
<div class="container">
<header>
<h1>這里可能是一個頁面標題</h1>
</header>
<main>
<p>主要內容的一個段落,</p>
<p>另一個主要段落,</p>
</main>
<footer>
<p>這里有一些聯系資訊</p>
</footer>
</div>
在組合組件時,內容分發API是非常有用的機制,
作用域插槽
2.1.0補充
作用域插槽是一種特殊型別的插槽,利用使用一個(能夠傳遞資料到)可重用模板替換已渲染元素,
在子組件中,只需將資料傳遞到插槽,就像你將prop傳遞給組件一樣:
<div class="child">
<slot text="hello from child"></slot>
</div>
在父級中,具有特殊屬性scope的<template>元素,表示它是作用域插槽的模板,scope的值對應一個臨時變數名,此變數接收從子組件中傳遞的prop物件:
<div class="parent">
<child>
<template scope="props">
<span>hello from parent</span>
<span>{{ props.text }}</span>
</template>s
</child>
</div>
如果我們渲染以上結果,得到的輸出會是:
<div class="parent">
<div class="child">
<span>hello from parent</span>
<span>hello from child</span>
</div>
</div>
作用域插槽更具代表性的用例是串列組件,允許組件自定義應該如何渲染串列每一項:
<my-awesome-list :items="items">
<!-- 作用域插槽也可以在這里命名 -->
<template slot="item" scope="props">
<li class="my-fancy-item">{{ props.text }}</li>
</template>
</my-awesome-list>
串列組件的模板:
<ul>
<slot name="item"
v-for="item in items"
:text="item.text">
<!-- fallback content here -->
</slot>
</ul>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/305714.html
標籤:其他
上一篇:手寫一個簡易的ajax,進行封裝
下一篇:Vue保姆級教程
