利用v-model實現(xiàn)自定義的表單組件
在vue中涡匀,表單都可以使用v-model來實現(xiàn)雙向數(shù)據(jù)綁定梨树,看著v-model很神奇拣凹,但實際上這是一個vue的語法糖(語法糖指并沒有實際為計算機語法添加新東西栓辜,只是使語法對于閱讀和使用的人來說更加容易理解)卜范,v-model實際是以下方式的簡寫
<input
v-bind:value="something"
v-on:input="something=$event.target.value"
>
如果能夠理解了上面的寫法刹悴,那么我們就可以自己實現(xiàn)一個v-model的表單組件
<custom-input
v-bing:value='something'
v-on:input="something=arguments[0]">
</custom-input>
這個組件想要生效那么需要有兩個必要的條件
- 接受一個value屬性
- 在有新的值的時候觸發(fā)input事件
<body>
<div id="box">
<h4>利用v-model實現(xiàn)自定義的表單組件</h4>
<h6>CounterBtn組件的值<s>{{btnValue}}</s></h6>
<counter-btn v-model='btnValue'></counter-btn>
<!--
v-model='btnValue'
相當于
:value="btnValue"
@input="btnValue=argument[0]"
子組件中的$emit()發(fā)送的事件必須命名為input行楞,因為在v-model中存在@input會自動接收
而argument[0]可以理解為一種簡寫,
在我們通常寫的父組件接收子組件發(fā)送的數(shù)據(jù)的寫法是在方法中的參數(shù)就是子組件的數(shù)據(jù)
所以argument[0]也就是獲取的子組件的$emit發(fā)送的數(shù)據(jù)中的data
這樣的話我們就相當于
在我們的子組件中的input事件被觸發(fā)的時候會發(fā)送數(shù)據(jù)到父組件颂跨,父組件在接收到數(shù)據(jù)后在更新自身的數(shù)據(jù)
相當于實現(xiàn)了v-model
-->
<form>
<labek for="count">綁定值到input隱藏域中</labek>
<input type="text" name="count" :value="btnValue.res" id="count">
<!--一般情況下input會被設置為type為hidden-->
</form>
</div>
<script src="./node_modules/vue/dist/vue.min.js"></script>
<script>
new Vue({
data:{
btnValue:{}
},
components:{
'counter-btn':{
template:`
<div class="coutter-wrapper">
<button type="button" @click="plus">+</button>
<button type="button">{{result}}</button>
<button type="button" @click="minus">-</button>
</div>
`,
methods:{
minus(){
this.result--;
this.$emit('input',{res:this.result,other:'--'})
},
plus(){
this.result++;
this.$emit('input',{res:this.result,other:'++'})
}
},
data(){
return{
result:0
}
}
}
}
}).$mount('#box')
</script>
</body>
is
<body>
<div class="box">
<table>
<!--<tem></tem>-->
<tr is="tem"></tr>
</table>
<!--如果沒有使用模板方式敢伸,需要注意在ul,ol恒削,table這些元素中放入組件不會被渲染池颈,如例子中的tem雖然內(nèi)容顯示了,但并不是被渲染在table內(nèi)钓丰,需要使用is的寫法-->
</div>
<script>
Vue.component('tem', {
template: `
<h3>全局組件</h3>
`
})
new Vue({}).$mount(".box")
</script>
</body>
子組件索引(ref)
在組件中有時我們需要在javascript中直接訪問子組件躯砰。為此我們可以使用ref為子組件指定一個索引ID,由此來獲得組件內(nèi)的參數(shù)携丁,數(shù)據(jù)等內(nèi)容
<body>
<template id="temp">
<h3>模板</h3>
</template>
<div id="box" @click="click">
<tem ref="demo"></tem>
<p ref="txt">
Lorem ipsum dolor sit amet, consectetur.
</p>
</div>
<script>
Vue.component(
"tem", {
template: "#temp",
data: function () {
return {
msg: "模板的數(shù)據(jù)"
}
},
methods:{
show(){
return "模板的show方法"
}
}
}
)
new Vue({
el: "#box",
methods: {
click: function () {
console.log(this.$refs.demo.msg); //模板的數(shù)據(jù)
console.log(this.$refs.demo.show()); //模板的show方法
console.log(this.$refs.txt.innerText); //Lorem ipsum dolor sit amet, consectetur.
}
}
})
</script>
</body>
當ref和v-for一起使用的時候琢歇,ref是一個數(shù)組,數(shù)組內(nèi)包含對應的子組件
需要特別注意的是ref只在組件渲染完成后才能填充梦鉴,并且ref并不是響應式的
異步組件
在頁面載入的時候李茫,我們有時候不需要一次性的將所有的組件全部載入,尤其是當一些組件是需要在被觸發(fā)才需要顯示的情況肥橙,一次性全部加載會讓我們第一次加載的文件變大魄宏,拖慢我們的搜詞加載速度,所以我們需要用到異步組件
<div id="box">
<p>{{msg}}</p>
<async></async>
</div>
<script>
Vue.component('async', function (resolve, reject) {
setTimeout(function () {
// 將組件定義傳入 resolve 回調(diào)函數(shù)
resolve({
template: '<div>我會在setimeout執(zhí)行完成后顯示</div>'
})
}, 1000)
})
new Vue({
el: "#box",
data: {
msg: "正常展示會在頁面加載完成時顯示"
}
})
</script>
</body>
vue允許我們?yōu)榻M件定義一個工廠函數(shù)存筏,使用promise宠互,在需要的時候觸發(fā)工廠函數(shù)渲染,并且會將結果存儲起來椭坚,用于后面的再次渲染予跌,這里的settimeout只是為了示例效果,我們可以根據(jù)實際開發(fā)需要定義觸發(fā)resolve的條件
如果我們想要所有的組件都是異步加載的善茎,那么可以采用下面兩種寫法
new Vue({
//...
components:{
Banner: () => ({
component: import("components/Banner")
})
}
})
const Banner= Vue.component("Slider", resolve=>{
require(['../Slider.vue'], resolve)
})
高級異步組件
自 2.3.0 起券册,異步組件的工廠函數(shù)也可以返回一個如下的對象:
const AsyncComp = () => ({
// 需要加載的組件。應當是一個 Promise
component: import('./MyComp.vue'),
// 加載中應當渲染的組件
loading: LoadingComp,
// 出錯時渲染的組件
error: ErrorComp,
// 渲染加載中組件前的等待時間。默認:200ms汁掠。
delay: 200,
// 最長等待時間略吨。超出此時間則渲染錯誤組件。默認:Infinity
timeout: 3000
})
注意考阱,當一個異步組件被視作為vue-router的路由使用時,這些高級選項都是無效的鞠苟,因為切換路由前就會提前加載所需的異步組件乞榨。另外,如果要在路由組件中使用改寫法当娱,需要vue-router2.4.0以上版本