利用v-model實(shí)現(xiàn)自定義的表單組件
在vue中,表單都可以使用v-model來實(shí)現(xiàn)雙向數(shù)據(jù)綁定,看著v-model很神奇,但實(shí)際上這是一個(gè)vue的語法糖(語法糖指并沒有實(shí)際為計(jì)算機(jī)語法添加新東西,只是使語法對(duì)于閱讀和使用的人來說更加容易理解),v-model實(shí)際是以下方式的簡寫
<input
v-bind:value="something"
v-on:input="something=$event.target.value"
>
如果能夠理解了上面的寫法,那么我們就可以自己實(shí)現(xiàn)一個(gè)v-model的表單組件
<custom-input
v-bing:value='something'
v-on:input="something=arguments[0]">
</custom-input>
這個(gè)組件想要生效那么需要有兩個(gè)必要的條件
- 接受一個(gè)value屬性
- 在有新的值的時(shí)候觸發(fā)input事件
<body>
<div id="box">
<h4>利用v-model實(shí)現(xiàn)自定義的表單組件</h4>
<h6>CounterBtn組件的值<s>{{btnValue}}</s></h6>
<counter-btn v-model='btnValue'></counter-btn>
<!--
v-model='btnValue'
相當(dāng)于
:value="btnValue"
@input="btnValue=argument[0]"
子組件中的$emit()發(fā)送的事件必須命名為input,因?yàn)樵趘-model中存在@input會(huì)自動(dòng)接收
而argument[0]可以理解為一種簡寫,
在我們通常寫的父組件接收子組件發(fā)送的數(shù)據(jù)的寫法是在方法中的參數(shù)就是子組件的數(shù)據(jù)
所以argument[0]也就是獲取的子組件的$emit發(fā)送的數(shù)據(jù)中的data
這樣的話我們就相當(dāng)于
在我們的子組件中的input事件被觸發(fā)的時(shí)候會(huì)發(fā)送數(shù)據(jù)到父組件,父組件在接收到數(shù)據(jù)后在更新自身的數(shù)據(jù)
相當(dāng)于實(shí)現(xiàn)了v-model
-->
<form>
<labek for="count">綁定值到input隱藏域中</labek>
<input type="text" name="count" :value="btnValue.res" id="count">
<!--一般情況下input會(huì)被設(shè)置為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這些元素中放入組件不會(huì)被渲染,如例子中的tem雖然內(nèi)容顯示了,但并不是被渲染在table內(nèi),需要使用is的寫法-->
</div>
<script>
Vue.component('tem', {
template: `
<h3>全局組件</h3>
`
})
new Vue({}).$mount(".box")
</script>
</body>
子組件索引(ref)
在組件中有時(shí)我們需要在javascript中直接訪問子組件。為此我們可以使用ref為子組件指定一個(gè)索引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>
當(dāng)ref和v-for一起使用的時(shí)候,ref是一個(gè)數(shù)組,數(shù)組內(nèi)包含對(duì)應(yīng)的子組件
需要特別注意的是ref只在組件渲染完成后才能填充,并且ref并不是響應(yīng)式的
異步組件
在頁面載入的時(shí)候,我們有時(shí)候不需要一次性的將所有的組件全部載入,尤其是當(dāng)一些組件是需要在被觸發(fā)才需要顯示的情況,一次性全部加載會(huì)讓我們第一次加載的文件變大,拖慢我們的搜詞加載速度,所以我們需要用到異步組件
<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>我會(huì)在setimeout執(zhí)行完成后顯示</div>'
})
}, 1000)
})
new Vue({
el: "#box",
data: {
msg: "正常展示會(huì)在頁面加載完成時(shí)顯示"
}
})
</script>
</body>
vue允許我們?yōu)榻M件定義一個(gè)工廠函數(shù),使用promise,在需要的時(shí)候觸發(fā)工廠函數(shù)渲染,并且會(huì)將結(jié)果存儲(chǔ)起來,用于后面的再次渲染,這里的settimeout只是為了示例效果,我們可以根據(jù)實(shí)際開發(fā)需要定義觸發(fā)resolve的條件
如果我們想要所有的組件都是異步加載的,那么可以采用下面兩種寫法
new Vue({
//...
components:{
Banner: () => ({
component: import("components/Banner")
})
}
})
const Banner= Vue.component("Slider", resolve=>{
require(['../Slider.vue'], resolve)
})
高級(jí)異步組件
自 2.3.0 起,異步組件的工廠函數(shù)也可以返回一個(gè)如下的對(duì)象:
const AsyncComp = () => ({
// 需要加載的組件。應(yīng)當(dāng)是一個(gè) Promise
component: import('./MyComp.vue'),
// 加載中應(yīng)當(dāng)渲染的組件
loading: LoadingComp,
// 出錯(cuò)時(shí)渲染的組件
error: ErrorComp,
// 渲染加載中組件前的等待時(shí)間。默認(rèn):200ms。
delay: 200,
// 最長等待時(shí)間。超出此時(shí)間則渲染錯(cuò)誤組件。默認(rèn):Infinity
timeout: 3000
})
注意,當(dāng)一個(gè)異步組件被視作為vue-router的路由使用時(shí),這些高級(jí)選項(xiàng)都是無效的,因?yàn)榍袚Q路由前就會(huì)提前加載所需的異步組件。另外,如果要在路由組件中使用改寫法,需要vue-router2.4.0以上版本