Vue.js學習
一、瞭解Vue.js
1.1.1 Vue.js是什麼?
- 簡單小巧、漸進式、功能強大的技術棧
1.1.2 為什麼學習Vue.js?
- 學習曲線平緩、易上手、功能強大、輕便
- 目前最流行的三大框架之一,適用範圍廣
- 升職加薪 ------ 哈哈哈哈哈哈哈哈
1.1.3 Vue.js的模式
- MVVM模式,檢視層和資料層的雙向繫結,讓我們無需再去關係DOM操作的事情,更過的精力放在資料和業務邏輯上去
1.1.4 Vue.js環境搭建
- script
- vue腳手架工具vue-cli搭建。
二、資料繫結,指令,事件
2.1.1 vue例項和資料繫結
一、
<script src="http://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
通過建構函式Vue就可以建立一個Vue的根例項,並啟動Vue應用---入口
var app = new Vue({
el: '',
data: {
}
})
二、
其中必不可少的一個選項就是el,el用於指定一個頁面中已存在的DOM元素來掛載Vue例項
三、
通過Vue例項的data選項,可以宣告應用內需要雙向繫結的資料。建議所有會用到的資料都預先在data內宣告,這樣不至於將資料散落在業務邏輯中,難以維護。也可以指向一個已經有的變數
四、
掛載成功後,我們可以通過app.$el
來訪問該元素。Vue提供了很多常用的例項屬性與方法,都已 $
開頭,比如 $el
,Vue例項本身也代理了data物件裡所有屬性,所以可以這樣訪問
五、
如果是訪問data裡的屬性,用app.屬性名
2.1.2
created: 例項穿件完成後呼叫,此階段完成了資料的觀測等,但尚未掛載,$el
還不可用。需要初始化處理一些資料時會比較有用。------還未掛載
mounted: el
掛載到例項上後呼叫,一般我們的第一個業務邏輯會從這裡開始。------剛剛掛載
beforeDestroy: 例項銷燬之前呼叫。主要解綁一些使用addEventListener監聽的事件等。
2.1.3 文字插值和表示式
語法: 使用雙大括號(Mustache語法)"{{ }}"是最基本的文字插值方法,他會自動將我們雙向繫結的資料實時顯示出來
用法:
- 在{{ }}中,處了簡單的繫結屬性值外,還可以使用JavaScript表示式進行簡單的運算、三元運算等
- Vue.js只支援單個表示式,不支援語句和流控制
2.2.1 過濾器
Vue支援在{{ }}插值的尾部新增一小管道符"|"對資料進行過濾,經常用於格式化文字,比如字母全部大寫、貨幣千位使用逗號分隔等。過濾的規則是自定義的,通過給Vue例項新增選項filters來設定
過濾器:{{data | filter1 | filter2}}
{{data | formatData(1,2)}}中的第一個和第二個引數,分別對應過濾器的第二個和第三個引數
2.2.2 指令和事件
指令( Directives )是 Vue 模板中最常用的一項功能,它帶有字首 v-,能幫我們
快速完成DOM操作。迴圈渲染。顯示和隱藏
- v-text:—————解析文字 和{{ }} 作用一樣
- v-html:————— 解析html
- v-bind—————–vbind 的基本用途是動態更新 HTML 元素上的屬性,比如 id 、class 等,本節只介紹基本章節,後面章節會更加深入詳細講述
- v-on——————它用來繫結事件監聽器
v-on具體介紹
在普通元素上, von 可以監聽原生的 DOM 事件,除了 click 外,還有
dblclick、 keyup, mousemove 等。表示式可以是一個方法名,這些方法都寫在 Vue 例項的 methods屬性內,並且是函式的形式,函式內的 this 指向的是當前 Vue 例項本身,因此可以直接使用 this.xxx 的形式來訪問或修改資料vue中用 到的所有方法都定義在methods中
2.2.3 語法糖
語法糖是指在不影響功能的情況下 , 新增某種簡潔方法實現同樣的效果 , 從而更加方便程
序開發。
- v-bind ——> : (冒號)
- v-on ——> @
運用以上知識點,總和一個小demo:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>demo</title>
<style>
.data {
background: red;
height: 18px;
}
</style>
</head>
<body>
<div id="app">
{{name}} <br>
{{name | formatDate}}
<br>
<div v-html="html"></div>
<span v-text="weather"></span>
<br>
<div v-bind:class="className"></div>
<button v-on:click="click">{{countnum}}</button>
</div>
<script src="http://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
var plusDate = function(value){
return value < 10 ? '0' + value : value
}
var app = new Vue({
el : '#app',
data : {
name: new Date(),
html: '<div>你好</div>',
weather: '今天天氣不錯',
className: 'data',
countnum: 0
},
filters:{
formatDate: function(value) {
var date = new Date(value)
var year = date.getFullYear()
var month = plusDate(date.getMonth()+1)
var day = plusDate(date.getDate())
var hours = plusDate(date.getHours())
var min = plusDate(date.getMinutes())
var sec = plusDate(date.getSeconds())
return year + '--' + month + '--' + day + ' ' + hours + ':' + min + ':' + sec
}
},
mounted: function(){
var _this = this
this.timer = setInterval(function(){
_this.name = new Date()
},1000)
},
methods: {
click: function(){
this.countnum = this.countnum + 1
}
},
beforeDestroy: function(){
clearInterval(this.timer)
}
})
</script>
</body>
</html>
三、 計算屬性
3.1 什麼是計算屬性
我們己經可以搭建出一個簡單的 Vue 應用,在模板中雙向繫結一些資料或表示式了。但是表示式如果過長,或邏輯更為複雜時,就會變得雕腫甚至難以閱讀和維護
<div>
{{ text.split ( ’,’ ) •reverse () . join (’,’)}}
</div>
- 這裡的表示式包含 3 個操作,並不是很清晰,所以在遇到複雜的邏輯時應該使用 計算屬性
- 所有的計算屬性都以函式的形式寫在 Vue 例項內的computed 選項內,最終返回計算後的結果。
3.2 計算屬性用法
- 在一個計算屬性裡可以完成各種複雜的邏輯,包括運算、函式呼叫等,只要最終返回一個結果就可以。除了上例簡單的用法
- 計算屬性還可以依賴多個 Vue 例項的資料,只要其中任一資料變化,計算屬性就會重新執行,檢視也會更新
getter和setter
每一個計算屬性都包含一個 getter 和一個 setter,我們上面的兩個示例都是計算屬性的預設用法 , 只是利用了 getter來讀取。在你需要時,也可以提供一個 setter 函式 , 當手動修改計算屬性的值就像修改一個普通資料那樣時,就會觸發 setter函式,執行一些自定義的操作
計算屬性除了上述簡單的文字插值外,還經常用於動態地設定元素的樣式名稱 class 和內聯樣式 style
小技巧: 計算屬性還有兩個很實用的小技巧容易被忽略:
- 一、是計算屬性可以依賴其他計算屬性:
- 二、是計算屬性不僅可以依賴當前 Vue 例項的資料,還可以依賴其他例項的資料
3.3計算屬性快取
呼叫 methods 裡的方法也可以與計算屬性起到同樣的作用
頁面中的方法: 如果是呼叫方法,只要頁面重新渲染。方法就會重新執行,不需要渲染,則不需要重新執行
計算屬性:不管渲染不渲染,只要計算屬性依賴的資料未發生變化,就永遠不變
結論: 沒有使用計算屬性,在 methods 裡定義了一個方法實現了相同的效果,甚至該方法還可以接受引數,使用起來更靈活。既然使用 methods 就可以實現,那麼為什麼還需要計算屬性呢?原因就是計算屬性是基於它的依賴快取的。 一個計算屬性所依賴的資料發生變化時,它才會重新取值,所以text 只要不改變,計算屬性也就不更新
何時使用: -----------使用計算屬性還是 methods 取決於你是否需要快取,當遍歷大陣列和做大量計算時,應當使用計算屬性,除非你不希望得到快取。
計算屬性demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>計算屬性</title>
</head>
<body>
<div id="data">
{{fullName}} <br>
{{watch()}}
</div>
<script src="http://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#data',
data: {
firstName:'Cai',
lastName: 'hua'
},
computed: {
fullName: function(){
return this.firstName + ' ' + this.lastName
}
},
methods: {
watch: function(){
return this.firstName + ' ' + this.lastName
}
}
})
</script>
</body>
</html>
四、 v-bind以及class與style的繫結
應用場景: DOM 元素經常會動態地繫結一些 class 類名或 style 樣式
4.1 瞭解bind指令
v-bind的複習:
連結的 href 屬性和圖片的 src 屬性都被動態設定了,當資料變化時,就會重新渲染。
在資料繫結中,最常見的兩個需求就是元素的樣式名稱 class 和內聯樣式 style 的動態繫結,它們也是 HTML的屬性,因此可以使用 v-bind 指令。
我們只需要用 v-bind計算出表示式最終的字串就可以,不過有時候表示式的邏輯較複雜,使用字串拼接方法較難閱讀和維護,所以 Vue.js 增強了對 class 和 style 的繫結。
4.2 繫結 class 的幾種方式
4.2.1 物件語法
給 v-bind:class 設定一個物件,可以動態地切換 class,值對應true ,false
當 class 的表示式過長或邏輯複雜時,還可以繫結一個計算屬性,這是一種很友好和常見的用法,一般當條件多於兩個時, 都可以使用 data 或 computed
4.2.2 陣列語法
當需要應用多個 class 時, 可以使用陣列語法 , 給:class 繫結一個陣列,應用一個 class列表:
- 陣列成員直接對應className--類名
- 可以用三目運算實現,物件和陣列混用
4.2.3 在元件上使用 : 暫時不考慮—挖坑
4.3 繫結內聯樣式
使用 v-bind:style (即:style ) 可以給元素繫結內聯樣式,方法與 :class 類似,也有物件語法和陣列語法,看起來很像直接在元素上寫 CSS
注意 : css 屬性名稱使用駝峰命名( came!Case )或短橫分隔命名( kebabcase),應用多個樣式物件時 , 可以使用陣列語法,在實際業務 中,style 的陣列語法並不常用 , 因為往往可以寫在一個物件裡面, 而較為常用 的應當是計算屬性
使用 :style 時, Vue .js 會自動給特殊的 css 屬性名稱增加字首, 比如 transform 。
無需再加字首屬性!!!!
v-bind繫結demo:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>v-bind繫結</title>
<style>
.divStyle{
width: 88px;
height: 88px;
background: red;
}
.borderStyle{
border: 8px solid black;
}
.color{
color: red;
}
.size{
font-size: 28px;
}
.blueClass{
color: blue;
}
.font{
font-size: 36px;
}
</style>
</head>
<body>
<div id="demo">
//物件語法 <br>
<div v-bind:class="{divStyle : isActive, borderStyle : isBorder}"></div>
<hr>
//陣列語法<br>
<div v-bind:class="[colorClass,sizeClass]">Hello word</div>
<hr>
//物件和陣列混用
<div v-bind:class="[{blueClass : isBlue},fontClass]">你好!</div>
<hr>
//繫結內聯樣式
<div v-bind:style="{'background':background,'fontSize':fontSize + 'px'}">真好!</div>
</div>
<script src="http://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
var app = new Vue({
el:'#demo',
data:{
isActive: true,
isBorder: true,
colorClass:"color",
sizeClass: "size",
isBlue:true,
fontClass:"font",
background: 'red',
fontSize:'56'
}
})
</script>
</body>
</html>
五、vueJS中的內建指令
5.1 基本指令
5.1.1 v-cloak一般與display:none進行結合使用
作用:解決初始化慢導致頁面閃動的最佳實踐
5.1.2 v-once
定義:它的元素和元件只渲染一次
5.2 條件渲染指令
5.2.1 v-if, v-eles-if ,v-else
用法: 必須跟著屁股走
v-if的弊端 :
Vue 在渲染元素時 ,出於效率考慮,會盡可能地複用已有的元素而非重新渲染, 因此會出現烏龍,只會渲染變化的元素,也就是說,input元素被複用了
解決方法: 加key,唯一,提供key值可以來決定是否複用該元素
5.2.2 v-show
- 只改變了css屬性display
v-if和v-show的比較
v-if:
- 實時渲染:頁面顯示就渲染,不顯示。我就給你移除
v-show:
- v-show的元素永遠存在也頁面中,只是改變了css的display的屬性
5.3 列表渲染指令v-for
用法: 當需要將一個陣列遍歷或列舉一個物件屬性的時候迴圈顯示時,就會用到列表渲染指令 v-for。
兩種使用場景:
- 遍歷多個物件
- 遍歷一個物件的多個屬性
v-for demo
<body>
<div id="demo">
//遍歷多個物件一定是遍歷的陣列
//帶索引的寫法:括號的第一個變數,代表item,第二個代表index
<ul>
<li v-for="vuestu in vueStudy">{{vuestu.name}}</li>
</ul>
<br>
//遍歷一個物件的多個屬性
//拿到value,key,index的寫法 v-k-i--外開
<div v-for="(value,key,index) in women">{{index}}-----{{key}}------{{value}}</div>
</div>
<script src="http://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
var app = new Vue({
el:'#demo',
data:{
vueStudy:[
//每個物件對應一個li
{name:'敲程式碼'},
{name:'看資料'},
{name:'看蔡華鵬部落格'}
],
women:{
grid1: '張柏芝',
grid2: '迪麗熱巴',
grid3: '高圓圓'
}
}
})
</script>
</body>
5.4 陣列更新,過濾與排序
改變陣列的一系列方法:
- push() 在末尾新增元素
- pop() 將陣列的最後一個元素移除
- shift() 刪除陣列的第一個元素
- unshift():在陣列的第一個元素位置新增一個元素
- splice() :可以新增或者刪除函式—返回刪除的元素
三個引數:- 第一個引數 表示開始操作的位置
- 第二個參數列示:要操作的長度
- 第三個為可選引數:
- sort():排序
- reverse()
兩個陣列變動vue檢測不到:
- 改變陣列的指定項
- 改變陣列長度
改變指定項: Vue.set(app.arr,1,”car”);
app.arr.splice(1): 改變陣列長度
過濾:filter
解決方法:
1. set
2. splice
5.5 方法和事件
[object MouseEvent]
5.5.1 基本用法
v-on繫結的事件類似於原生 的onclick等寫法:
methods:{
handle:function (count) {
count = count || 1;
this.count += count;
}
}
如果方法中帶有引數,但是你沒有加括號,預設傳原生事件物件event
5.5.2 修飾符
- 在vue中傳入event物件用 $event
- 向上冒泡
stop:阻止單擊事件向上冒泡
prevent:提交事件並且不過載頁面
self:只是作用在元素本身而非子元素的時候呼叫
once: 只執行一次的方法
可以監聽鍵盤事件:
<input @keyup.13 ="submitMe"> ——指定的keyCode
vueJS為我們提供了:
.enter
.tab
.delete 等等、、、、、、
六、 表單與v-model
6.1 基本用法
v-model:
VUE提供了vmodel指令, 用於在表單類元素上雙向繫結事件
input和textarea
可以用於input框,以及textarea等
注意: 所顯示的值只依賴於所繫結的資料,不再關心初始化時的插入的value
單選按鈕:
- 單個單選按鈕,直接用v-bind繫結一個布林值,用v-model是不可以的
- 如果是組合使用,就需要v-model來配合value使用,繫結選中的單選框的value值,此處所繫結的初始值可以隨意給
核取方塊:
- 單個核取方塊,直接用定一個布林值,可以用v-model可以用v-bind
- 多個核取方塊– 如果是組合使用,就需要v-model來配合value使用,v-model繫結一個陣列—如果繫結的是字串,則會轉化為true。false,與所有繫結的核取方塊的checked屬性相對應
下拉框:
- 如果是單選,所繫結的value值初始化可以為陣列,也可以為字串,有value直接優先匹配一個value值,沒有value就匹配一個text值
- 如果是多選,就需要v-model來配合value使用,v-model繫結一個陣列,與核取方塊類似
- v-model一定是繫結在select標籤上
總結一下:
如果是單選,初始化最好給定字串,因為vmodel此時繫結的是靜態字串或者布林值如果是多選,初始化最好給定一個陣列
6.2 繫結值
單選按鈕
只需要用v-bind給單個單選框繫結一個value值,此時,v-model繫結的就是他的value值核取方塊
下拉框
在select標籤上繫結value值對option並沒有影響
6.3 修飾符
-
lazy
v-model預設是在input輸入時實時同步輸入框的資料,而lazy修飾符,可以使其在失去焦點或者敲Enter鍵之後在更新 -
number
將輸入 的字串轉化為number型別 -
trim
trim自動過濾輸入過程中收尾輸入的空格
七、 可複用性的元件詳解
7.1 使用元件的原因
- 作用:提高程式碼的複用性
7.2 元件的使用方法
1. 全域性註冊
Vue.component('my-component',{
template:'<div>我是元件的內容</div>'
})
優點:所有的vue例項都可以用
缺點:許可權太大,容錯率降低
2. 區域性註冊
var app = new Vue({
el:'#app',
components:{
'my-component':{
template: '<div>我是元件的內容</div>'
}
}
})
3. vue元件的模板在某些情況下會受到html標籤的限制,比如 <table>
中只能還有 <tr>
, <td>
這些元素,所以直接在table中使用元件是無效的,此時可以使用is屬性來掛載元件
<table>
<tbody is="my-component"></tbody>
</table>
7.3 元件使用的奇淫技巧
- 推薦使用小寫字母加-進行命名(必須) child, my-componnet命名元件
- template中的內容必須被一個DOM元素包括 ,也可以巢狀
- 在元件的定義中,除了template之外的其他選項---data,computed,methods
- data必須是一個方法
7.4 使用props傳遞資料 父親向兒子傳遞資料
- 在元件中使用props來從父親元件接收引數,注意,在props中定義的屬性,都可以在元件中直接使用
props來自父級,而元件中data return的資料就是元件自己的資料,兩種情況作用域就是元件本身,可以在template,computed,methods中直接使用
- props的值有兩種,一種是字串陣列,一種是物件
- 可以使用v-bind動態繫結父元件來的內容
7.5 單向資料流
- 解釋 : 通過 props 傳遞資料 是單向的了, 也就是父元件資料變化時會傳遞給子元件,但是反過來不行。
- 目的 :是儘可能將父子元件解稿,避免子元件無意中修改了父元件的狀態。
- 應用場景: 業務中會經常遇到兩種需要改變 props 的情況
一種是父元件傳遞初始值進來,子元件將它作為初始值儲存起來,在自己的作用域下可以隨意使用和修改。這種情況可以在元件 data 內再宣告一個資料,引用父元件的 props
步驟一:註冊元件
步驟二:將父元件的資料傳遞進來,並在子元件中用props接收
步驟三:將傳遞進來的資料通過初始值儲存起來
<div id="app">
<my-comp init-count="666"></my-comp>
</div>
<script>
var app = new Vue({
el:'#app',
components:{
'my-comp':{
props:['init-count'],
template:'<div>{{count}}</div>',
data:function () {
return{
count:this.initCount
}
}
}
}
})
</script>
另一種情況就是 prop 作為需要被轉變的原始值傳入。這種情況用計算屬性就可以了
步驟一:註冊元件
步驟二:將父元件的資料傳遞進來,並在子元件中用props接收
步驟三:將傳遞進來的資料通過計算屬性進行重新計算
<body>
<div id="data">
<input type="text" v-model="width">
<my-conponent :width="width"></my-conponent>
</div>
<script src="http://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
var app = new Vue({
el:'#data',
data:{
width:''
},
components:{
'my-conponent':{
props:['width'],
template:'<div :style="style"></div>',
computed:{
style:function(){
return{
width:this.width+'px',
background:'red',
height:'30px'
}
}
}
}
}
})
</script>
</body>
7.6 資料驗證
- @ vue元件中camelCased (駝峰式) 命名與 kebabcase(短橫
線命名)
@ 在html中,
myMessage
和mymessage
是一致的,,因此在元件中的html
中使用必須使用kebab-case(短橫線)命名方式。在html中不允許使用駝
峰!!!!!!
@ 在元件中, 父元件給子元件傳遞資料必須用短橫線。在template中,必須使用駝峰命名方式,若為短橫線的命名方式。則會直接保錯。
@ 在元件的data中,用this.XXX引用時,只能是駝峰命名方式。若為短橫線
的命名方式,則會報錯。
驗證的 type 型別可以是:
- String
- Number
- Boolean
- Object
- Array
- Function
Vue.component ( ’ my-compopent ’, {
props : {
//必須是數字型別
propA : Number ,
//必須是字串或數字型別
propB : [String , Number] ,
//布林值,如果沒有定義,預設值就是 true
propC: {
type : Boolean ,
default : true
},
//數字,而且是必傳
propD: {
type: Number ,
required : true
},
//如果是陣列或物件,預設值必須是一個函式來返回
propE: {
type : Array ,
default : function () {
return [] ;
}
},
//自定義一個驗證函式
propF: {
validator : function (value) {
return value > 10;
}
}
}
});
7.7 元件通訊
元件關係可分為父子元件通訊、兄弟元件通訊、跨級元件通訊
7.7.1 自定義事件—子元件給父元件傳遞資料
使用v-on 除了監昕 DOM 事件外,還可以用於元件之間的自定義事件。JavaScript 的設計模式
一一觀察者模式, dispatchEvent
和 addEventListener
這兩個方法。 Vue 元件也有與之類似的一套模式,子元件用$emit()
來 觸發事件
,父元件用$on()
來 監聽子元件的事件
。
直接來程式碼
- 第一步:自定義事件
- 第二步: 在子元件中用$emit觸發事件,第一個引數是事件名,後邊的引數是要傳遞的資料
- 第三步:在自定義事件中用一個引數來接受
<body>
<div id="app">
<p>您好,您現在的銀行餘額是{{total}}元</p>
<btn-compnent @change="handleTotal"></btn-compnent>
<!-- <button-component @change="money"></button-component> -->
</div>
<script src="http://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
var app = new Vue({
el: '#app',
data: {
total: 0
},
components: {
'btn-compnent': {
template: '<div>\
<button @click="handleincrease">+10000</button> \
<button @click="handlereduce">-10000</button>\
</div>',
data: function () {
return {
count: 0
}
},
methods: {
handleincrease: function () {
this.count = this.count + 10000;
this.$emit('change', this.count);
},
handlereduce: function () {
this.count = this.count - 10000;
this.$emit('change', this.count);
}
}
}
},
methods: {
handleTotal: function (total) {
this.total = total;
}
}
})
</script>
</body>
7.7.2 在元件中使用v-model
$emit
的程式碼,這行程式碼實際上會觸發一個 input事件
, ‘input’
後的引數就是傳遞給v-model繫結的屬性的值
v-model 其實是一個語法糖,這背後其實做了兩個操作:
- v-bind 繫結一個 value 屬性
- v-on 指令給當前元素繫結 input 事件
要使用v-model,要做到:
- 接收一個 value 屬性。
- 在有新的 value 時觸發 input 事件
<body>
<div id="app">
<p>您好,您現在的銀行餘額是{{total}}元</p>
<btn-compnent v-model="total"></btn-compnent>
</div>
<script src="http://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
//關於
var app = new Vue({
el: '#app',
data: {
total: 0
},
components: {
'btn-compnent': {
template: '<div>\
<button @click="handleincrease">+1</button> \
<button @click="handlereduce">-1</button>\
</div>',
data: function () {
return {
count: 0
}
},
methods: {
handleincrease: function () {
this.count++;
----------------------注意觀察.這一行,emit的是input事件----------------
this.$emit('input', this.count);
},
handlereduce: function () {
this.count--;
this.$emit('input', this.count);
}
}
}
},
methods: {
/* handleTotal:function (total) {
this.total = total;
}*/
}
})
</script>
</body>
7.7.3 非父元件之間的通訊
官網描述:
<div id="app">
<my-acomponent></my-acomponent>
<my-bcomponent></my-bcomponent>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js">
</script>
<script>
Vue.component('my-acomponent', {
template: '<div><button @click="handle">點選我向B元件傳遞資料</button></div>',
data: function () {
return {
aaa: '我是來自A元件的內容'
}
},
methods: {
handle: function () {
this.$root.bus.$emit('lala', this.aaa);
}
}
})
Vue.component('my-bcomponent', {
template: '<div></div>',
created: function () {
//A元件在例項建立的時候就監聽事件---lala事件
this.$root.bus.$on('lala', function (value) {
alert(value)
});
}
})
</script>
父鏈:this.$parent
Vue.component('child-component', {
template: '<button @click="setFatherData">通過點選我修改父親的資料</button>',
methods: {
setFatherData: function () {
this.$parent.msg = '資料已經修改了'
}
}
})
子鏈:this.$refs
提供了為子元件提供索引的方法,用特殊的屬性ref為其增加一個索引
var app = new Vue({
el: '#app',
data: {
//bus中介
bus: new Vue(),
msg: '資料還未修改',
formchild: '還未拿到'
},
methods: {
getChildData: function () {
//用來拿子元件中的內容 ---- $refs
this.formchild = this.$refs.c.msg;
}
}
})
7.8使用slot分發內容
7.8.1 什麼是slot(插槽)
為了讓元件可以組合,我們需要一種方式來混合父元件的內容與子元件自己的模板。這個過程被稱為 內容分發.Vue.js 實現了一個內容分發 API,使用特殊的 ‘slot’ 元素作為原始內容的插槽。
7.8.2 編譯的作用域
在深入內容分發 API 之前,我們先明確內容在哪個作用域裡編譯。假定模板為:
<child-component>
{{ message }}
</child-component>
message 應該繫結到父元件的資料,還是繫結到子元件的資料?答案是父元件。元件作用域簡單地說是:
- 父元件模板的內容在父元件作用域內編譯
- 子元件模板的內容在子元件作用域內編譯
7.8.3 插槽的用法
- 父元件的內容與子元件相混合,從而彌補了檢視的不足
-
混合父元件的內容與子元件自己的模板
單個插槽:
<div id="app">
<my-component>
<p>我是父元件的內容</p>
</my-component>
</div>
Vue.component('my-component',{ template:'
<div>\
<slot>\ 如果父元件沒有插入內容,我就作為預設出現\
</slot>\
</div>' })
具名插槽:
具名插槽:
<name-component>
<h3 slot="header">我是標題</h3>
<p>我是正文內容</p>
<p>正文內容有兩段</p>
<p slot="footer">我是底部資訊</p>
</name-component>
Vue.component('name-component',{ template:'
<div>\
<div class="header">\n' + '
<slot name="header">\n' + ' \n' + ' </slot>\n' + '
</div>\n' + '
<div class="contatiner">\n' + '
<slot>\n' + ' \n' + ' </slot>\n' + '
</div>\n' + '
<div class="footer">\n' + '
<slot name="footer">\n' + '\n' + ' </slot> \n' + '
</div>'+ ' </div>' })
7.8.4 作用域插槽
作用域插槽是一種特殊的slot,使用一個可以複用的模板來替換已經渲染的元素——從子元件獲取資料
template模板是不會被渲染的
Vue.component('my-component',{ template:'
<div>\
<slot text="我是來自子元件的資料" ss="fdjkfjlsd" name="abc">\
</slot>\
</div>' })
7.8.5 訪問slot
通過this.$slots.(NAME)
mounted:function () {
//訪問插槽
var header = this.$slots.header;
var text = header[0].elm.innerText;
var html = header[0].elm.innerHTML;
console.log(header)
console.log(text)
console.log(html)
}
7.9 元件高階用法–動態元件
VUE給我們提供 了一個元素叫component
- 作用是: 用來動態的掛載不同的元件
- 實現:使用is特性來進行實現的
直接甩程式碼:
<body>
<div id="data">
<component :is ="show"></component>
<button @click="msg('a')">第一句</button>
<button @click="msg('b')">第二句</button>
<button @click="msg('c')">第三句</button>
<button @click="msg('d')">第四句</button>
</div>
<script src="http://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
Vue.component('msga', {
template: '<div>鋤禾日當午</div>',
data:function(){
return{
}
}
})
Vue.component('msgb', {
template: '<div>汗滴禾下土</div>',
data:function(){
return{
}
}
})
Vue.component('msgc', {
template: '<div>誰知盤中餐</div>',
data:function(){
return{
}
}
})
Vue.component('msgd', {
template: '<div>粒粒堅辛苦</div>',
data:function(){
return{
}
}
})
var app = new Vue({
el:'#data',
data:{
show:'msga'
},
methods:{
msg:function(value){
this.show = 'msg' + value
}
}
})
</script>
</body>
八、 自定義指令
自定義指令的基本用法
和元件類似分全域性註冊和區域性註冊,區別就是把component
換成了derective
鉤子函式
指令定義函式提供了幾個鉤子函式(可選):
- bind: 只呼叫一次,指令第一次繫結到元素時呼叫,用這個鉤子函式可以定義一個在繫結時執行一次的初始化動作。
- inserted: 被繫結元素插入父節點時呼叫(父節點存在即可呼叫,不必存在於 document中)。
- update: 被繫結元素所在的模板更新時呼叫,而不論繫結值是否變化。通過比較更新前後的繫結值,可以忽略不必要的模板更新(詳細的鉤子函式引數見下)。
- componentUpdated: 被繫結元素所在模板完成一次更新週期時呼叫。
- unbind: 只呼叫一次, 指令與元素解綁時呼叫。
鉤子函式的引數有:
el: 指令所繫結的元素,可以用來直接操作 DOM 。
-
binding: 一個物件,包含以下屬性:
- name: 指令名,不包括 v- 字首。
- value: 指令的繫結值, 例如: v-my-directive=”1 + 1”, value 的值是2。
- oldValue: 指令繫結的前一個值,僅在 update 和componentUpdated 鉤子中可用。無論值是否改變都可用。
- expression: 繫結值的字串形式。 例如 v-my-directive=”1 + 1” , expression 的值是“1 + 1”。
- arg: 傳給指令的引數。例如 v-my-directive:foo, arg 的值是 “foo”。
- modifiers: 一個包含修飾符的物件。 例如: v-my-directive.foo.bar, 修飾符物件,,,modifiers 的值是 { foo: true, bar: true }。
vnode: Vue 編譯生成的虛擬節點。
oldVnode: 上一個虛擬節點,僅在 update 和 componentUpdated 鉤子中可用。
自定義的指令
<div v-cuihua:.a.b.c="obq"></div>
九 、render函式
9.1 render函式初步瞭解
template下只允許有一個子節點
<template id="hdom">
<div>
<h1 v-if="level==1">
<slot></slot>
</h1>
<h2 v-if="level==2">
<slot></slot>
</h2>
<h3 v-if="level==3">
<slot></slot>
</h3>
</div>
</template>
<script>
//是用vue元件定義
// Vue.component('child',{
// props:['level'],
// template:'#hdom'
// })
//使用render函式進行定義元件
Vue.component('child', {
render: function (createElement) {
return createElement('h' + this.level,
this.$slots.default);
},
props: ['level']
})
9.2 render函式的第一個引數
在render函式的方法中,引數必須是createElement,createElement的型別是function,render函式的第一個引數可以是 String | Object | Function
Vue.component('child', {
// ----第一個引數必選
//String--html標籤
//Object---一個含有資料選項的物件
//FUnction---方法返回含有資料選項的物件
render: function (createElement) {
alert(typeof createElement)
// return createElement('h1')
// return createElement({
// template:'<div>鋤禾日當午</div>'
// })
var domFun = function () {
return {
template: '<div>鋤禾日當午</div>'
}
}
return createElement(domFun());
}
});
9.3 render函式的第二個引數
Vue.component('child', {
// ----第二個引數可選,第二個引數是資料物件----只能是Object
render: function (createElement) {
return createElement({
template: '<div>我是龍的傳人</div>'
}, {
'class': {
foo: true,
baz: false
},
style: {
color: 'red',
fontSize: '16px'
},
//正常的html特性
attrs: {
id: 'foo',
src: 'http://baidu.com'
},
//用來寫原生的Dom屬性
domProps: {
innerHTML: '<span style="color:blue;font-size: 18px">我是藍色</span>'
}
})
}
});
9.3 render函式的第三個引數
第三個引數也是可選===String | Array—作為我們構建函式的子節點來使用的
Vue.component('child', {
// ----第三個引數是可選的,可以是 String | Array---代表子節點
render: function (createElement) {
return createElement('div', [
createElement('h1', '我是h1標題'),
createElement('h6', '我是h6標題')
])
}
});
9.4 this.$slots在render函式中的應用
第三個 引數存的就是VNODE
createElement(‘header’,header), 返回的就是VNODE
var header = this.$slots.header; //–這返回的內容就是含有=VNODE的陣列
Vue.component('my-component', {
render: function (createElement) {
debugger
var header = this.$slots.header; //--這返回的內容就是含有=V
NODE的陣列
var main = this.$slots.default;
var footer = this.$slots.footer;
return createElement('div', [
createElement('header', header),
createElement('main', main),
createElement('footer', footer)
]);
}
})
9.5 在render函式中使用props傳遞資料
<div id="app">
<button @click="switchShow">點選切換美女</button> {{show}}
<my-component :show="show">
</my-component>
</div>
<script>
Vue.component('my-component', {
props: ['show'],
render: function (createElement) {
var imgsrc;
if (this.show) {
imgsrc = 'img/001.jpg'
} else {
imgsrc = 'img/002.jpg'
}
return createElement('img', {
attrs: {
src: imgsrc
},
style: {
width: '600px',
height: '400px'
}
});
}
})
</script>
9.6 v-model在render函式中的使用
<!--<my-component :name="name" @input="showName"></my-componen
t>-->
<my-component :name="name" v-model="name"></my-component>
<br> {{name}}
<script>
Vue.component('my-component', {
render: function (createElement) {
var self = this;//指的就是當前的VUE例項
return createElement('input', {
domProps: {
domProps: {
value: self.name
},
value: self.name
},
on: {
input: function (event) {
debugger
var a = this;
//此處的this指的是什麼?指的就是window
self.$emit('input', event.target.value)
}
}
})
},
props: ['name']
})
</script>
9.7 作用域插槽在render函式中的使用
Vue.component('my-component', {
render: function (createElement) {
return createElement('div', this.$scopedSlots.default({
text: '我是子元件傳遞過來的資料',
msg: 'scopetext'
}))
}
})
9.8 函式化元件的應用
使用context的轉變
// this.text----context.props.text
//this.$slots.default-----context.children
functional: true,表示該元件無狀態無例項
十、 使用vue-cli腳手架一鍵搭建工程
首先電腦上要安裝最新版的nodeJS.官網下載,安裝完之後安裝淘寶npm映象
npm install -g cnpm --registry=https://registry.npm.taobao.org
五部走:
- 全域性安裝vue-cli
npm install -g vue-cli
- 進入目錄–初始化專案
vue init webpack my-project
- 進入專案
cd my-project
- 安裝依賴
npm install
- 啟動專案
npm run dev
目錄結構的分析
├── build // 專案構建(webpack)相關程式碼 記憶:(夠賤) 9個
│ ├── build.js // 生產環境構建程式碼
│ ├── checkversions.js // 檢查node&npm等版本
│ ├── devclient.js // 熱載入相關
│ ├── devserver.js // 構建本地伺服器
│ ├── utils.js // 構建配置公用工具
│ ├── vueloader.conf.js // vue載入器
│ ├── webpack.base.conf.js // webpack基礎環境配置
│ ├── webpack.dev.conf.js // webpack開發環境配置
│ └── webpack.prod.conf.js // webpack生產環境配置
二、
├── config// 專案開發環境配置相關程式碼 記憶: (環配) 3個
│ ├── dev.env.js // 開發環境變數(看詞明意)
│ ├── index.js //專案一些配置變數
│ └── prod.env.js // 生產環境變數
三、
├──node_modules// 專案依賴的模組 記憶: (依賴) *個
四、
├── src// 原始碼目錄 5
1
│ ├── assets// 資源目錄
│ │ └── logo.png
2
│ ├── components// vue公共元件
│ │ └── Hello.vue
3
│ ├──router// 前端路由
│ │ └── index.js// 路由配置檔案
4
│ ├── App.vue// 頁面入口檔案(根元件)
5
│ └── main.js// 程式入口檔案(入口js檔案)
五、
└── static// 靜態檔案,比如一些圖片,json資料等
│ ├── .gitkeep
剩餘、
├── .babelrc// ES6語法編譯配置
├── .editorconfig// 定義程式碼格式
├── .gitignore// git上傳需要忽略的檔案格式
├── index.html// 入口頁面
├── package.json// 專案基本資訊
├── README.md// 專案說明
十一、 vue-router路由和前端狀態管理
11.1 vue-router路由基本載入
簡單四步走
- 安裝
npm install --save vue-router
- 引用
import router from 'vue-router'
Vue.use(router)
- 配置路由檔案,並在vue例項中注入
var rt = new router({
routes:[{
path:'/',//指定要跳轉的路徑
component:HelloWorld//指定要跳轉的元件
}]
})
new Vue({
el: '#app',
router:router,
components: { App },
template: '<App/>'
})
- 確定檢視載入的位置
<router-view></router-view>
11.2 vue-router路由的跳轉
<router-link to="/"></router-link>
<template>
<ul>
<li>
<router-link to="/helloworld">HELLO WORLD</router-link>
</li>
<li>
<router-link to="/helloearth">HELLO EARTH</router-link>
</li>
</ul>
</template>
11.3 vue-router路由引數的傳遞
- 必須在路由內加入路由的name
- 必須在path後加/: +傳遞的引數
- 傳遞引數和接收引數看下邊程式碼
<router-link
:to="{name: helloearth,params:{msg: 只有一個地球}}">
HELLO WORLD
</router-link>
讀取引數: $route.params.XXX
方式:===/helloworld/你好世界
<router-link
:to="{path: '/helloearth',query:{msg: 只有一個地球}}">
HELLO WORLD
</router-link>
方式:===/helloworld?name=XX&count=xxx
函式模式
你可以建立一個函式返回 props。這樣你便可以將引數轉換成另一種型別,將靜態值與基於路由的值結合等等。
const router = new VueRouter({
routes: [
{ path: '/search', component: SearchUser, props: (route) => ({
query: route.query.q }) }
]
})
11.4.1 Axios之get請求詳解
axios的簡介:
axios 是一個基於Promise 用於瀏覽器和 nodejs 的 HTTP 客戶端,它本身具有以下特徵:
- 從瀏覽器中建立 XMLHttpRequest
- 從 node.js 發出 http 請求
- 支援 Promise API
- 攔截請求和響應
- 轉換請求和響應資料
- 取消請求
- 自動轉換JSON資料
- 客戶端支援防止 CSRF/XSRF
- 安裝
npm install axios
- 引入載入
import axios from 'axios'
- 將axios全域性掛載到VUE原型上
Vue.prototype.$http = axios;
- 發出請求 以cnode社群API為例子
// 為給定 ID 的 user 建立請求
使用傳統的function
getData(){
var self = this;
this.$http.get('https://cnodejs.org/api/v1/topics')
.then(function (res) {
//此處的this指向的不是當前vue例項
self.items = res.data.data
console.log(res.data.data)
})
.catch(function (err) {
console.log(err)
})
}
// 可選地,上面的請求可以這樣做
兩種傳遞引數的形式
axios.get('/user', {
params: {
ID: 12345
}
})
axios.get('/user', {
ID: 12345
})
---------------------------------
axios.get('https://cnodejs.org/api/v1/topics?page=1&limit=15')
- 使用CNODE社群官方的API為例展開學習
- 獲取主題列表API:https://cnodejs.org/api/v1/topics
- 引數:page頁碼
- limit 每頁顯示的數量
11.4.2 Axios之post請求詳解
// 為給定 ID 的 user 建立請求
使用傳統的function
getData(){
var self = this;
this.$http.post(url,{
page:1,
limit:10
})
.then(function (res) {
//此處的this指向的不是當前vue例項
self.items = res.data.data
console.log(res.data.data)
})
.catch(function (err) {
console.log(err)
})
}
POST傳遞資料有兩種格式:
- form-data ?page=1&limit=48
- x-www-form-urlencoded { page: 1,limit: 10 }
在axios中,post請求接收的引數必須是formdata
qs外掛—qs.stringify
11.5 Vuex之store
用來管理狀態,共享資料,在各個元件之間管理外部狀態如何使用?
- 第一步:引入vuex,並通過use方法使用它
- 第二步: 建立狀態倉庫
- 第三步:通過this.$sore.state.XXX直接拿到需要的資料
//建立狀態倉庫,注意Store,state不能改
var store = new Vuex.Store({
state:{
XXX:xxx
}
})
//直接通過this.$sore.state.XXX拿到全域性狀態
11.6 Vuex的相關操作
vuex狀態管理的流程
view———>actions———–>mutations—–>state————>view
除了能夠獲取狀態如何改變狀態呢?
//建立狀態倉庫,注意Store,state不能改
var store = new Vuex.Store({
state:{
XXX:xxx
},
mutations:{
}
})
this.$store.commit(XXX);
// 此處的XXX是你在mucations中定義的方法名
var store = new Vuex.Store({
state:{
XXX:xxx
},
mucations:{
a:function(state){
}
},
actions:{
b:function(context){
context.commit('a');
}
}
})
// 如何呼叫
this.$store.dispatch(XXX);
getters:{
}
this.$store.getters.getCount
注意:actions提交的是mutation,而不是直接變更狀態
actions可以包含非同步操作,但是mutation只能包含同步操作
The early bird catches the worm
相關文章
- vue.js 學習筆記Vue.js筆記
- 共同學習Vue.js ---webpackVue.jsWeb
- Vue.js原始碼學習三 —— 事件 Event 學習Vue.js原始碼事件
- Vue.js 原始碼學習五 —— provide 和 inject 學習Vue.js原始碼IDE
- Vue.js原始碼學習一 —— 資料選項 State 學習Vue.js原始碼
- 我的 Vue.js 學習日記 (二)Vue.js
- Vue.js 學習之Webpack安裝配置Vue.jsWeb
- Vue.js學習第二課 如何安裝Vue.js
- WordPress 和 Vue.js 的學習資源推薦Vue.js
- Vue.js入門學習 -- 計算屬性Computed( 十一)Vue.js
- Vue.js 學習筆記之四:Vue 元件基礎Vue.js筆記元件
- Vue.js 學習筆記之七:使用現有元件Vue.js筆記元件
- 我的 Vue.js 學習日記 (七) – 事件與修飾符Vue.js事件
- Vue.js 學習筆記之六:構建更復雜的元件Vue.js筆記元件
- Vue.js學習(八)—— 樹形結構下拉框元件vue-treeselectVue.js元件
- 我的 Vue.js 學習日記 (六) – v-for 與 table 的 增、刪、排序、明細Vue.js排序
- 轉前端 vue.js 學習筆記-1.2-使用 let 與 const 定義常量變數前端Vue.js筆記變數
- Vue.js基礎學習(三) -------------動態繫結v-bind的介紹和使用Vue.js
- Vue.js設計與實現學習總結(第四章7)偵聽器Vue.js
- 【vue深入學習第2章】Vue.js 中的 Ajax 處理:vue-resource 庫的深度解析Vue.js
- Vue.js設計與實現學習總結(第四章6)計算屬性Vue.js
- Vue.js設計與實現學習總結(第四章5)排程執行Vue.js
- 錢端 P0 學習筆記:基於 vue.js 2.3.x 的偽雙向繫結筆記Vue.js
- 深度學習——學習目錄——學習中……深度學習
- 邂逅VUE.JSVue.js
- 深度學習學習框架深度學習框架
- 學習ThinkPHP,學習OneThinkPHP
- 從零開始學 Web 之 Vue.js(六)Vue的元件WebVue.js元件
- 比官方文件更易懂的Vue.js教程!包你學會!Vue.js
- 強化學習-學習筆記3 | 策略學習強化學習筆記
- 機器學習-整合學習機器學習
- 前端學習之Bootstrap學習前端boot
- 如何學習機器學習機器學習
- Vue.js + Docker 部署Vue.jsDocker
- Vue.js – 起手式Vue.js
- vue.js原始碼Vue.js原始碼
- 機器學習整合學習—Apple的學習筆記機器學習APP筆記
- 機器學習——監督學習&無監督學習機器學習