title: vue-模闆文法
date: 2020-09-16 21:27:17
tags: Vue
categories: 前端
githubBlog:Click Me
1.Vue模闆文法
1.1插值操作
mustache文法{{expr}}
expr可以是變量,常量,表達式,會自動根據Vue中的data進行渲染
<div id="app">
<h2>{{message}}</h2>
<h2>{{message+message}}</h2>
<h2>{{v*2}}</h2>
<h2>{{firstName+" "+lastName}}</h2>
<h2>{{firstName}}{{lastName}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: "test",
firstName: "hello",
lastName: "world",
v: 100
}
})
</script>
v-once
此時,資料隻從vue中得到資料初始化渲染一次,之後該元件(标簽内)的資料不會随着data中的資料變化
<!--v-once作用域是整個标簽-->
<div id="app">
<h2 v-once>{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
message: "test",
}
})
</script>
v-html
類似于innerHtml(),把資料進行解析後顯示
v-text
類似于innerText(),把原資料顯示出來
v-pre
忽略mustache直接顯示出兩個大括号
v-cloak
在Vue渲染html标簽前,讓被渲染的元素隐藏,不顯示原生的{ {} }等文法
1.2動态綁定屬性
v-bind
為标簽的屬性綁定Vue的data值,綁定後屬性值将根據這個data動态改變
v-bind可用冒号
:
代替
<div id="app">
<!-- 綁定屬性的操作 -->
<img v-bind:src="imgurl" alt="">
<a :href="url">百度一下</a>
</div>
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
imgurl: 'https://www.baidu.com/img/flexible/logo/pc/result.png',
url: 'www.baidu.com'
}
})
</script>
動态參數
https://cn.vuejs.org/v2/guide/syntax.html#%E5%8A%A8%E6%80%81%E5%8F%82%E6%95%B0
v-bind綁定class
通過對象綁定
<h2 :class={ 類名1:boolean,類名2:boolean}>vue</h2>
<h2 class="title" :class="{'active': isActive, 'line': isLine}">Hello World</h2>
<script src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
isActive: true,
isLine: false
}
})
</script>
通過一個對象的形式,若類名對應的值(vue中的data)為true值會為标簽綁定class,false則不會,可與原生的class共存。若對象過于複雜,可通過methods或計算屬性傳回一個對象。
通過數組綁定
<h2 class="title" :class="[類名, 類名,···]">Hello World</h2>
<h2 class="title" :class="[active, line]">Hello World</h2>
類名可以是一個變量,常量,表達式,最終代表需要綁定的類名
v-bind綁定style
利用v-bind:style來綁定一些CSS内聯樣式。
通過對象綁定
<h1 :style="{屬性名:屬性值,屬性名:屬性值,···}">{{massage}}</h1>
<h1 :style="{color:colorStyle,'background-color':bkColorStyle,fontSize:fSize+'px'}">{{massage}}</h1>
屬性名可以是小駝峰式,或者短橫線分隔式(需單引号括起)
屬性值可以是常量,變量,表達式
通過數組綁定
<div v-bind:style="[baseStyles, overridingStyles]"></div>
<script>
const vm = new Vue({
el: '#app',
data: {
//可以是駝峰式也可以短橫線分隔式
baseStyles: {color:'red','background-color':'gray'},
overridingStyles: {fontSize:'20px'}
}
})
</script>
數組中放的是對象,每個對象代表一個css樣式,本質上就是通過對象綁定
1.3方法與計算屬性
**方法(methods):**類似于函數,隻不過它屬于指定的vue對象
**計算屬性(computed):**本質上是屬性,隻是多了getter和setter方法(類似于bean),并且與方法methods相比,具備緩存功能,可以動态監聽,當資料改變時才會調用getter
<div id="app">
<h2>{{fullName}}</h2>
<h2>{{fullName2}}</h2>
<!--方法調用必須加上括号(在事件監聽時不用)-->
<h2>{{fullName3()} }</h2>
<h2>{{fullName4()} }</h2>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
firstName:'Alan',
lastName:'Turing'
},
computed:{
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
// 當執行vm.fullName = 'John Doe'會被調用
set: function (newValue) {
let names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
},
//當沒有set方法時,可簡化為如下,并且可省略 :function
fullName2:function() {
return (this.firstName+' '+this.lastName).toUpperCase();
}
},
methods:{
fullName3:function(){
return this.firstName+' '+this.lastName;
},
//可省略 :function
fullName4(){
return this.firstName+' '+this.lastName;
}
}
})
</script>
1.4偵聽器和濾波器
偵聽器:偵聽vue執行個體中的資料變化,一旦資料發生變化就會執行回調函數
<script>
const vm = new Vue({
el: '#app',
data:{
val=100;
}
watch:{
//如果data中的val發生改變,就會執行下方函數
val:function(newVal,oldVal){
console.log(newVal+' '+oldVal);
}
})
</script>
濾波器:在輸出内容時,給内容添加修飾。
<div id="app">
<!-- 最終顯示 ¥100.00 -->
<span>總價:{{totalPrice |showPrice } }</span>
</div>
<script>
const vm = new Vue({
el: '#app',
data:{
totalPrice=100;
}
filters:{
showPrice(totalPrice){
return "¥"+totalPrice.toFixed(2);
}
})
</script>
1.5事件監聽
v-on
- 作用:綁定事件監聽器
- 縮寫:@
- 預期:Function | Inline Statement | Object
- 參數:event
v-on:click="func1"
,引号内填寫函數名,不帶括号時,預設傳入一個event,帶括号時按正常情況傳遞參數,當需要傳遞事件對象時,參數為$event
<div id="app">
<!-- 點選後會輸出mouseEvent-->
<button v-on:click="func1">按鈕1</button>
<!-- 點選後會輸出123 abc-->
<button @click="func2('123','abc')">按鈕2</button>
<!-- 點選後會輸出mouseEvent undefine-->
<button @click="func2">按鈕3</button>
<!-- 點選後會輸出123 mouseEvent-->
<button @click="func2('123',$event)">按鈕4</button>
</div>
<script>
const vm = new Vue({
el: '#app',
methods:{
func1(param1){
alert("This is btn1:"+param1) ;
},
func2(param1,param2){
alert("This is btn2:"+param1+' '+param2) ;
}
}
})
</script>
v-on修飾符
- .stop - 調用 event.stopPropagation()。
- .prevent - 調用 event.preventDefault()。
- .{keyCode | keyAlias} - 隻當事件是從特定鍵觸發時才觸發回調。
- .native - 監聽元件根元素的原生事件。
- .once - 隻觸發一次回調。
<!-- 阻止事件冒泡 -->
<button @click.stop="doThis">button</button>
<!-- 阻止預設行為發生,可省略doThis -->
<form @submit.prevent="doThis" action="url">
<input type="text">
<input type="submit">
</form>
<!-- 串聯修飾符 -->
<button @click.stop.prevent="doThis">button</button>
<!-- 鍵修飾符,指定别名或鍵代碼 -->
<input type="text" @keyup.enter="doThis" @keydown.10="doThis" >
<!-- 觸發一次回調 -->
<button @click.once="doThis">button</button>
關于修飾符的知識還很欠缺,例如不同修飾符順序引發不同的結果
一些鍵修飾别名:
-
.enter
-
.tab
-
(捕獲 “删除” 和 “倒退” 鍵).delete
-
.esc
-
.space
-
.up
-
.down
-
.left
-
.right
-
.ctrl
-
.alt
-
.shift
-
.meta
1.6條件渲染
if、else if、else
這三個指令類似于if、else、else if。Vue的條件指令可以根據表達式的值在DOM中渲染或銷毀元素或元件。
<div id="app">
<h3 v-if="score>=90">Excellent</h3>
<h3 v-else-if="score>=80">Good</h3>
<h3 v-else-if="score>=60">Ok</h3>
<h3 v-else>Fail</h3>
</div>
<script type="text/javascript" src="../js/vue.js"></script>
<script>
const vm = new Vue({
el: '#app',
data:{
score:90,
}
})
</script>
v-show
v-show
和
v-if
的用法類似,都是決定一個頁面是否被渲染。
差別:
v-if
當條件為false時,壓根不會有對應的元素在DOM中。
v-show
當條件為false時,僅僅是将元素的
display
屬性設定為
none
而已。
當需要在顯示與隐藏之間切片很頻繁時,使用`v-show`。
當隻有一次切換時,通過使用`v-if`。
1.7清單渲染
v-for
<!--周遊數組-->
<li v-for="value in arr">{{value}}</li>
<li v-for="(value,index) in arr">{{value}}-{{index}}</li>
<!--周遊對象-->
<li v-for="value in obj">{{value}}</li>
<li v-for="(value,key) in obj">{{value}}-{{key}}</li>
<li v-for="(value,key,index) in obj">{{value}}-{{key}}-{{index}}</li>
數組響應式更新
Vue具有資料綁定的功能,是以當vue執行個體中的資料發生改變時,視圖能做出改變響應。
對數組使用如下方法,都會使得視圖發生更新
//函數的具體用法有待了解
let arr;
arr.push();
arr.pop();
arr.unshift();
arr.shift();
arr.splice();
arr.sort();
arr.reverse();
唯一需要注意的是使用如下方式1的數組下标指派的方法,視圖并不會發生更新
//方式1
let arr=[{key:value}];
arr[0]={key2:value2}; //視圖并不更新
//方式2
let arr2={key:value};
arr2[0].key=value2; //本質上是修改對象的的屬性内容,視圖發生更新
//解決方式1視圖不更新的兩種方式
//通過splice方法為數組指派,具體用法有待了解
//通過vue自帶的方法為數組指派
Vue.set(this.arr,index,value);
1.8兩個練手小案例:
點選綁定樣式和購物車
1.9v-model表單綁定
你可以用指令在表單
v-model
、
<input>
及
<textarea>
元素上建立雙向資料綁定。它會根據控件類型自動選取正确的方法來更新元素。此外input中的value屬性也支援v-bind動态綁定。
<select>
v-model原理
v-model其實是一個文法糖,它負責監聽使用者的輸入事件以更新資料,并對一些極端場景進行一些特殊處理。它的背後本質上是包含兩個操作:
- 1.v-bind綁定一個value屬性
- 2.v-on指令給目前元素綁定input事件
會忽略所有表單元素的
v-model
、
value
、
checked
attribute 的初始值而總是将 Vue 執行個體的資料作為資料來源。你應該通過 JavaScript 在元件的
selected
選項中聲明初始值。
data
在内部為不同的輸入元素使用不同的 property 并抛出不同的事件:
v-model
- text 和 textarea 元素使用
property 和
value
事件;
input
- checkbox 和 radio 使用
property 和
checked
事件;
change
- select 字段将
作為 prop 并将
value
作為事件。
change
以下代碼等價:
文本
<div id="app">
<p>單行文本:Message is: { { message1 } }</p>
<input v-model="message1" placeholder="edit me">
<br>
<hr>
<span>多行文本: Multiline message is:</span>
<p style="white-space: pre-line;">{{ message2 } }</p>
<br>
<textarea v-model="message2" placeholder="add multiple lines"></textarea>
</div>
<script>
const vm = new Vue({
el: '#app',
data:{
message1:'' ,
message2:''
}
})
</script>
單選按鈕
<div id="app">
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<br>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<br>
<span>Picked: { { picked } }</span>
</div>
<script>
const vm = new Vue({
el: '#app',
data:{
picked: '',
}
})
</script>
原生的單選按鈕中,不同的按鈕需要通過一個相同的name來實作互斥,當使用v-model時,可通過綁定同一個value來實作互斥。
複選框
<h3>單個複選框</h3>
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked } }</label>
<h3>多個複選框</h3>
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>Checked names: { { checkedNames } }</span>
<script>
const vm = new Vue({
el: '#app',
data:{
checked:undefined,//初始化時給一個true則預設會被選中,false或其它非布爾值預設不選
checkedNames: [],
}
})
</script>
選擇框
<h3>單個選擇框</h3>
<div>
<select v-model="option">
<option disabled value="">請選擇</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: { { option } }</span>
</div>
<h3>多個選擇框</h3>
<div>
<select v-model="options" multiple style="width: 50px;">
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<br>
<span>Selected: { { options } }</span>
</div>
<script>
const vm = new Vue({
el: '#app',
data:{
option:'',
options: [],
}
})
</script>
修飾符
lazy修飾符:
- 預設情況下,v-model預設是在input事件中同步輸入框的資料的。
- 也就是說,一旦有資料發生改變對應的data中的資料就會自動發生改變。
- lazy修飾符可以讓資料在失去焦點或者回車時才會更新:
number修飾符:
- 預設情況下,如果希望使用者輸入數字,原生的input提供了type="number"的用法,但是在輸入框中無論我們輸入的是字母還是數字,都會被當做字元串類型進行處理。
- 是以可通過
<input v-model.number="age" type="number">
- 給
添加v-model
修飾符可以讓在輸入框中輸入的内容自動轉成數字類型:number
trim修飾符:
- 如果要自動過濾使用者輸入的首尾空白字元,可以給
添加v-model
修飾符:trim
<input v-model.trim="msg">
2.元件化開發
元件是可複用的 Vue 執行個體,且帶有一個名字,并且元件相對于Vue來說多了一些例如template模闆等功能,template使得元件内部可封裝某些标簽資料。
2.1.元件使用流程
基本使用
- 建立元件對象(最新vue手冊中已不使用Vue.extend()建立元件對象了)
- 調用Vue.component()方法注冊元件
- 在Vue執行個體的作用範圍内使用元件
<div id="app">
<!-- 3.在Vue執行個體挂載的标簽範圍内使用元件-->
<cpn></cpn><!-- 此标簽最終會由cpnObj中的template進行渲染-->
</div>
<cpn></cpn>
<script>
//1.建立元件對象
//注意template最終必須由一個根标簽包含,例如下方根标簽為div
//其中template代表該元件對象的模闆,該對象還可有data,methods等屬性
//這是使用Vue.extend方式(過時)
//通過構造器建立元件對象
// const cpnObj = Vue.extend({
// template:`
// <div>
// <h3>我是标題</h3>
// <div>我是内容</div>
// </div>
// `
// });
//直接使用javascript對象
const cpnObj = {
template:`
<div>
<h3>我是标題</h3>
<div>我是内容</div>
</div>
`
};
//2.将元件對象注冊為元件(元件标簽,元件對象)
Vue.component('cpn',cpnObj);
const vm = new Vue({
el: '#app',
});
</script>
文法糖
直接在注冊時傳入對象參數
<script>
//将定義元件對象,并注冊為元件(元件标簽,元件對象)
Vue.component('cpn',{
template:`
<div>
<h3>我是标題</h3>
<div>我是内容</div>
</div>
`
});
</script>
2.2全局元件和局部元件
全局元件:
凡是以Vue.component()進行注冊的都是全局元件,可以在任何挂載了Vue執行個體的标簽内使用
局部元件:
在Vue執行個體中注冊,或在元件中注冊為子元件的元件都是局部元件,他們的作用範圍限于各自注冊的執行個體(元件)中。
一個元件對象可在不同的作用域中注冊為不同的元件
代碼執行個體:
<div id="app">
<cpn2></cpn2>
<cpn1></cpn1>
</div>
<script>
//這是子元件對象,可(同時)在vue執行個體(或元件)中注冊
const cpnObj1 = {
template:`
<div>
<h3>标題1</h3>
</div>
`
};
//第一種:注冊成為子元件:
//1.構造元件2對象時,把元件對象cpnObj1代表的元件添加為元件2的子元件
const cpnObj2 = {
template:`
<div style="color: #ff0000">
<h3>标題2</h3>
<cpn1></cpn1>
</div>
`,
components:{
//元件标簽名:元件對象
cpn1:cpnObj1 //作用域僅在該元件中,(可用文法糖)
}
};
//2.将元件2對象注冊為元件(元件标簽,元件對象)
Vue.component('cpn2',cpnObj2); //全局元件:作用域在任何Vue執行個體中
//第二種:在Vue執行個體中注冊
const vm = new Vue({
el: '#app',
components:{
//元件标簽名:元件對象
cpn1:cpnObj1 //作用域僅在該Vue執行個體中(可用文法糖)
}
})
</script>
2.3分離模闆
可将元件的template分離出來,單獨寫在一個标簽中
使用script标簽
使用script标簽包裹template,并給定id,然後在元件對象中引用template的id即可
<script type="text/x-template" id="myCpn">
<div>
<h3>這是元件</h3>
</div>
</script>
<script type="text/javascript" src="../js/vue.js"></script>
<script>
const cpnObj = Vue.extend()
const vm = new Vue({
el: '#app',
components:{
cpn: {
template:'#myCpn' //引用script中的id
}
}
})
</script>
使用template标簽
與script标簽相比,不用指定type=“text/x-template”,其餘相同
<template id="myCpn">
<div>
<h3>這是元件</h3>
</div>
</template>
<script>
const cpnObj = Vue.extend()
const vm = new Vue({
el: '#app',
components:{
cpn: {
template:'#myCpn'
}
}
})
</script>
2.4元件data
問題引入:元件也是一個Vue執行個體,意味着元件也可以有自己的data,那麼當元件标簽使用多次時,每個元件标簽引用的是同一個data,這樣是明顯不合理的,即在元件複用的時候,它們應該引用不同的data對象。
解決方法:Vue強制規定在元件中必須把data寫成函數的形式,并且該函數傳回一個對象來作為該元件的data,利用函數的作用域來讓每個元件标簽引用不同的資料對象。
每一次使用元件,function中都會有一個對象被建立并指派給data
code
<div id="app">
<cpn></cpn>
</div>
<template id="myCpn">
<div>
<h3>這是元件:{{msg}}</h3>
</div>
</template>
<script>
const vm = new Vue({
el: '#app',
components:{
cpn:{
//此處的元件對象中的data使用的是函數
data(){
return {
msg:'message'
}
},
template: '#myCpn'
}
}
})
</script>
2.5父子元件的資料傳遞
子元件是無法通路父元件或Vue執行個體中的資料的,而在實際的開發中,常常需要把父元件的資料傳遞給子元件使用,是以Vue提供了父子元件間傳遞資料的方法。
值得注意的是:當一個元件1在某個元件2内部注冊為局部元件後不代表該元件1就是元件2的子元件了,隻能說明元件1是作用在元件2内部的局部元件。
判斷是否為一個元件的子元件看的是在template标簽中是否嵌套使用了元件标簽,例如在挂載了vue執行個體的div中使用元件标簽cpn,此時cpn就是vue的子元件
父元件=>子元件 props
父元件(Vue執行個體)把資料傳遞給子元件中的props屬性。
- 在子元件中的props中聲明自己的屬性(prop),用于接收父元件傳遞的資料
- 在使用該子元件标簽時,為該子元件的prop屬性指派或動态綁定變量
<div id="app">
<!-- 在使用元件時給attr1 prop指派-->
1:<cpn attr1="attribute1"></cpn>
<!-- 在使用元件時給attr2 prop動态綁定為vue執行個體中的val-->
2:<cpn :attr2="val"></cpn>
</div>
<template id="myCpn">
<div>
<h3>這是屬性1:{{attr1}}</h3>
<h3>這是屬性2:{{attr2}}</h3>
</div>
</template>
<script>
const vm = new Vue({
el: '#app',
data:{
val:'attribute2'
},
components:{
cpn:{
template: '#myCpn',
//聲明屬性,有數組和對象兩種形式,此處是數組
props:['attr1','attr2'] //屬性以字元串形式書寫
}
}
});
</script>
當需要對傳入子元件中的prop進行類型驗證或預設值等操作時,就需要采用對象文法,執行個體如下
<div id="app">
<!-- 在使用元件時給attr1 prop指派,類型必須是Number是以必須動态綁定-->
1:<cpn :attr1="num"></cpn>
<!-- 在使用元件時給attr2 prop動态綁定為vue執行個體中的val-->
2:<cpn :attr2="val"></cpn>
</div>
<template id="myCpn">
<div>
<h3>這是屬性1:{{attr1}}</h3>
<h3>這是屬性2:{{attr2}}</h3>
</div>
</template>
<script>
const vm = new Vue({
el: '#app',
data:{
val:'DeliveredParameter',
num:10
},
components:{
cpn:{
template: '#myCpn',
//聲明屬性:對象形式
props:{
attr1:{
type: Number,
//表示這個屬性attr1在使用元件時必須傳遞參數
//required: true
},
attr2:{
type: String,
default(){ //此處因該使用函數
return 'DefaultString';
}
}
}
}
}
});
</script>
支援的資料驗證類型:驗證都支援哪些資料類型呢?String,Number,Boolean,Array,Object,Date,Function,Symbol
子元件=>父元件 $emit
子元件通過觸發自定義事件傳遞資料
父元件(Vue執行個體)則通過v-on監聽子元件觸發的事件,并從參數中獲得資料。
<div id="app">
<!--此處的自定義事件出來函數不應該加括号,vue會自動傳遞參數,隻需在method中接收即可-->
<cpn @my-event="handler"></cpn>
</div>
<template id="myCpn">
<div>
<!--此處是普通的v-on-->
<button @click="BtnClick()">Click me!</button>
</div>
</template>
<script>
const vm = new Vue({
el: '#app',
data:{
val:'DeliveredParameter',
},
methods:{
handler(val){
console.log('handler is done:'+val);
}
},
components:{
cpn:{
template: '#myCpn',
//聲明屬性:對象形式
props:{
attr:{
type: String,
default(){ //此處因該使用函數
return 'DefaultString';
}
}
},
methods:{
BtnClick(){
//子元件通過$emit觸發自定義事件myEvent,并傳遞參數attr
this.$emit('my-event',this.attr);
}
}
}
}
});
</script>
2.6父子元件的互相通路
有時候,在父元件内可能會出現引用子元件中某個函數或變量的情況,vue提供了三個變量來實作父子元件間的互相通路。
父元件通路子元件: c h i l d r e n 或 children或 children或refs
子元件通路父元件:$parent
子元件通路根元件:$root
代碼示例:
<div id="app">
<cpn></cpn>
<cpn></cpn>
</div>
<template id="tem1">
<div>
<h3>I am son</h3>
<ccpn></ccpn>
<ccpn></ccpn>
</div>
</template>
<template id="tem2">
<div>
<h3>I am grandson</h3>
</div>
</template>
<script>
const vm = new Vue({
el: '#app',
data:{
val:'I am root',
},
methods:{
func1(){
//this.$children代表目前元件(Vue執行個體)下的所有子元件(Vue component)
console.log(this.$children[0].val);
}
},
components:{
cpn:{
template: '#tem1',
data(){
return{
val: 'I am son'
}
},
methods:{
func1(){
//this.$parent代表目前元件的父元件Vue
console.log(this.$parent.val);
}
},
//聲明屬性:對象形式
components: {
ccpn:{
template: '#tem2',
data() {
return {
val: 'I am grandson'
}
},
methods:{
func1(){
//this.$root代表目前元件的根元件Vue執行個體
console.log(this.$root.val);
}
}
},
}
},
}
});
</script>
采用$children形式得到的是包含所有子元件的數組,并且索引與順序有關
由于元件标簽中同一級别的标簽數量和标簽可能發生變化,是以這種方法顯然在修改時不太容易。
r e f s 就 可 避 免 這 個 問 題 t h i s . refs就可避免這個問題this. refs就可避免這個問題this.refs得到的是一個包含所有子元件的對象, r e f s 使 用 時 隻 需 要 為 每 個 子 組 件 指 定 一 個 鍵 , r e f = " i d " , 然 後 父 組 件 再 引 用 時 采 用 t h i s . refs使用時隻需要為每個子元件指定一個鍵,ref="id",然後父元件再引用時采用this. refs使用時隻需要為每個子元件指定一個鍵,ref="id",然後父元件再引用時采用this.refs.id即可通路子元件
<div id="app"> <cpn ref="first"></cpn> <cpn ref="second"></cpn> </div> <script> const vm = new Vue({ el: '#app', data: { val: 'I am root', }, methods: { func1() { console.log(this.$refs.first); } }, } </script>
2.7slot插槽
基本插槽
在編寫元件模闆的時候,會出現兩個模闆高度相似的情況,為了更好的複用模闆,vue提出了在元件模闆中引入插槽slot。slot标簽内表示預留一個位置可供其它html代碼或元件插入。提高了元件的複用性和可擴充性。
<div id="app">
<cpn></cpn><!-- 插槽内容為預設的button -->
<cpn><span>自定義内容1</span></cpn><!-- 插槽内容為自定義span -->
</div>
<template id="tem1">
<div>
<h3>我是元件</h3>
<!-- slot标簽内容為空,表示不提供預設内容 -->
<slot><button>預設内容</button></slot>
</div>
</template>
中沒有包含一個
若元件cpn的template
元素,則該元件起始标簽和結束标簽之間的任何内容都會被抛棄(即cpn标簽内部内容無效)。
<slot>
該插槽跟模闆的其它地方一樣可以通路相同的執行個體 property (也和vue元件擁有相同的“作用域”)
具名插槽
當一個模闆中需要有多個插槽的時候,如果在使用的時候vue預設把cpn标簽的内容區替換每個v-slot标簽,這個時候就需要為每個插槽指定名稱,并在使用時注明。
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<!-- 一個不帶name的<slot>出口會帶有隐含的名字“default”-->
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
在向具名插槽提供内容的時候,我們可以在一個元素上使用
<template>
指令,并以
v-slot
的參數的形式提供其名稱:v-slot可縮寫為#,使用縮寫時必須帶上插槽名,例如default
v-slot
<base-layout>
<template v-slot:header>
<h1>Here might be a page title</h1>
</template>
<!-- 任何沒有被包裹在帶有 v-slot 的 <template> 中的内容都會被視為預設插槽的内容。
下面的兩個p标簽也可包裹在<template v-slot:default><template>标簽裡
-->
<p>A paragraph for the main content.</p>
<p>And another one.</p>
<template #:footer>
<p>Here's some contact info</p>
</template>
</base-layout>
作用域插槽
由于元件的編譯作用域原因,父元件中無法通路子元件的資料,意味着當父元件向子元件中的slot中插入内容時無法通路到子元件中的資料。
為了解決這一問題,vue提供了作用域插槽,即在為每個執行個體slot綁定一個function,在把子元件的資料傳遞到該function的作用域中,實作了每個插槽都有自己單獨的作用域。
本質上是:為每個執行個體的slot标簽提供一個作用域,子元件可把資料綁定到slot作用域裡,然後父元件在往slot中插入東西時,可以通路slot作用域中的資料。
CODE
<div id="app">
<!-- 沒有插入時 插槽顯示預設内容-->
<cpn></cpn>
<!-- 将template标簽内容作為插槽内容插入 -->
<cpn>
<!-- 此處為該slot命名一個作用域myScope,并根據作用域名通路v-bind:綁定的val(實際上是user的别名)-->
<template v-slot:default="myScope">
<span>自定義顯示年齡:{{myScope.val.age}}</span>
</template>
</cpn>
</div>
<template id="tem1">
<div>
<h3>我是元件</h3>
<!-- v-bind:此處把子元件data()中的user綁定到slot執行個體作用域,并取名為val-->
<slot v-bind:val="user"><span>預設顯示子元件data()中的user.name(姓名):{{user.name}}</span></slot>
</div>
</template>
<script>
const vm = new Vue({
el: '#app',
components:{
cpn:{
template: '#tem1',
data(){
return{
user: {
name:'Qian',
age:21,
}
}
},
},
}
});
</script>
獨占插槽
當被提供的内容隻有預設插槽時,元件的标簽才可以被當作插槽的模闆來使用,不需要被template标簽包裹。這樣我們就可以把
v-slot
直接用在元件上:
<current-user v-slot:default="slotProps">
{ { slotProps.user.firstName } }
</current-user>
<!-- 其中的:default可以省略 -->
當元件内有多個插槽時,為所有的插槽使用完整的基于 <template>
的文法:即每個插槽内容均包裹于template,且指定v-slot:default(othername)
附(一):參考:
阿清部落格:https://aqingya.cn/articl/92af846d.html
官網文檔:https://cn.vuejs.org/v2/guide/
附(二)快捷鍵:
"string".log +tab = console.log("string")
div#a + tab = <div id="a"></div>
div.b + tab = <div class="b"></div>