vue2組件進(jìn)階與插槽詳解(推薦!)
一、組件進(jìn)階
1.v-model語法
v-model指令我們的一個初印象就是表單數(shù)據(jù)實(shí)現(xiàn)綁定雙向,一修改同步修改,那么本質(zhì)是什么?
博主認(rèn)為v-mode語法本質(zhì)上是簡化了書寫操作。觸發(fā)v-model需要滿足兩個條件的(標(biāo)紅部分是語法規(guī)定部分不可自定義)
- data中數(shù)據(jù)變化,表單的值也會變化 :value="data中的屬性名"
- 表單的值發(fā)生變化,data中的數(shù)據(jù)也會變化 @input="data中的屬性名=$event.target.value"
當(dāng)滿足了就可直接寫上v-model="我們data中的屬性名"
舉個例子:
<template> <div> <h1>根組件App.vue</h1> <!-- 1.v-model = "msg" (1)data中的數(shù)據(jù)變化,表單的值也會變化 :value="msg" (2)表單的值發(fā)生變化,data中的數(shù)據(jù)也會變化 @input="msg=$event.target.value" --> <input type="text" v-model="msg" /> <hr /> <!-- 這種寫法與上面寫法功能一致 --> <input type="text" :value="msg" @input="msg = $event.target.value" /> <hr /> <!-- 這種寫法也與上面寫法一致 --> <input type="text" :value="msg" @input="doInput" /> <hr /> </div> </template> <script> export default { data() { return { msg: "" }; }, methods: { doInput(e) { this.msg = e.target.value; } } }; </script> <style> </style>
效果演示:
可見:當(dāng)我們直接用v-model="屬性名“這種方法寫簡化了書寫的難度達(dá)到了同樣的效果。
2.ref與$ref語法
這個語法可使用操作dom元素。每個 vue 的組件實(shí)例上,都包含一個$refs 對象,里面存儲著對應(yīng)的DOM 元素或組件的引用。
注意點(diǎn):
當(dāng)ref="自定義名"是寫在組件身上就可以得到該對象實(shí)例vue
綁定是ref,調(diào)用是$refs
1.綁定dom寫法:<標(biāo)簽 ref="自定義名"></標(biāo)簽>
<div ref="aaa" class="box"></div> <input ref="bbb" type="text"> <my-goods ref="ccc" ></my-goods>
2.調(diào)用dom寫的:this.$refs.自定義屬性名
console.log(this.$refs.aaa); console.log(this.$refs.bbb); console.log(this.$refs.ccc); // 調(diào)用子組件方法 console.log(this.$refs.ccc.doClick());//都包含一個$refs 對象因此可已獲取標(biāo)簽里面的方法(組件)
參考下面這個例子:
父組件:App.vue
<template> <div> <h1>我是父組件</h1> <button @click="onAdd">點(diǎn)我查看ref打印的啥</button> <div ref="aaa" class="box"></div> <input ref="bbb" type="text"> <my-goods ref="ccc" ></my-goods> </div> </template> <script> import MyGoods from '@/components/MyGoods.vue' export default { components: { MyGoods }, data() { return { } }, methods: { onAdd() { console.log(this); console.log(this.$refs.aaa); console.log(this.$refs.bbb); console.log(this.$refs.ccc); // 調(diào)用子組件方法 console.log(this.$refs.ccc.doClick()); }, } } </script> <style> </style>
子組件:MyGoods.vue
<template> <div> <p>商品名稱:小米</p> <p>商品價格:{{ price }}</p> <button @click="doClick">點(diǎn)我購買</button> </div> </template> <script> export default { props:{ value:Number }, data(){ return{ price:'999' } }, methods: { doClick() { console.log("點(diǎn)擊了購買"); return 0//當(dāng)不寫的時候調(diào)用了方法沒有return會提示undefinded } } } </script> <style> </style>
實(shí)現(xiàn)效果:
3.dynamic動態(tài)組件
什么是動態(tài)組件: 讓多個組件使用同一個掛載點(diǎn)并動態(tài)切換,這就是動態(tài)組件。
通過設(shè)置組件名,讓一個掛載點(diǎn)可以切換不同的組件。
語法格式:
<component :is="組件名"></component>
舉個例子:
父組件App.vue
<template> <div> <h1>我是父組件</h1> <button @click="comName='login'">登錄</button> <button @click="comName='user'">信息</button> <component :is="comName"></component> </div> </template> <script> import login from '@/components/login.vue' import user from '@/components/user.vue' export default { components: { login, user }, data() { return { comName:"user" } } } </script> <style> </style>
子組件 user.vue
<template> <div> <p>我是個人信息組件</p> </div> </template> <script> export default { name:"user" } </script> <style> </style>
子組件 login.vue
<template> <div> <p>我是登錄組件</p> </div> </template> <script> export default { name:"login" } </script> <style> </style>
實(shí)現(xiàn)效果:
可以看到我們通過<component :is="組件名">找到相應(yīng)的標(biāo)簽運(yùn)行
4.this.$nextTick()
是用來將我們vue的異步操作進(jìn)行放在頁面dom渲染前面。想要在修改數(shù)據(jù)后立刻得到更新后的DOM結(jié)構(gòu),可以使用Vue.nextTick()
上個例子:
<template> <div> <h1>我是父組件</h1> <input type="text" v-if="flag" ref="input"> <button v-else @click="doClick">點(diǎn)我開始輸入</button> </div> </template> <script> export default { data() { return { flag: false } }, methods: { doClick() { this.flag = true this.$nextTick( () => {//一定要箭頭函數(shù),因?yàn)榧^函數(shù)的this指向上一層作用域與原本的this是同一個 this.$refs.input.focus() } ) } } } </script> <style> </style>
實(shí)現(xiàn)的效果:
當(dāng) this.flag = true執(zhí)行完成之后頁面應(yīng)該是執(zhí)行渲染在頁面的操作,但是我們的 vue是異步的微任務(wù)(Vue將開啟一個異步更新隊列,視圖需要等隊列中所有數(shù)據(jù)變化完成之后,再統(tǒng)一進(jìn)行更新),渲染的時候找不到ref="input"這個dom就會報錯,因此需要就用 this.$nextTick來將需要的操作放在渲染之前。
可看上圖:當(dāng)我寫在外面的時候就會報錯。
原理:vue操作dom是異步的操作,如果需要同步顯示出來需要利用this.$nextTick()將異步操作提前放在dom樹更新前
二、匿名|具名|作用域插槽
插槽概念:
slot相當(dāng)于是組件里面的一個內(nèi)置的開關(guān),打開了這個開關(guān)就可以在復(fù)用組件的同時修改單個組件中的HTML的結(jié)構(gòu)。用來解決組件復(fù)用的同時可以對單個組件進(jìn)行修改操作,讓組件變得更加靈活
1.匿名插槽
我們在父中調(diào)用子組件,在復(fù)用組件的同時修改單個組件不受影響
插槽書寫結(jié)構(gòu):
父傳:<子組件名>HTML結(jié)構(gòu)</子組件名>
子收: <slot>此處寫默認(rèn)值</slot>
我們一起來看看這個例子:
父組件:App01(匿名插槽).vue
<template> <div> <h1>我是父組件</h1> <goods><button>已下單</button></goods> <goods></goods> <goods ><button disabled>已賣完</button></goods> <goods><a href="#">點(diǎn)我跳轉(zhuǎn)</a></goods> </div> </template> <script> import goods from '@/components/goods.vue' export default { components:{goods} } </script> <style> </style>
子組件:goods.vue
<template> <div class="son"> <h3>我是子組件</h3> <h4>商品名稱</h4> <!-- slot相當(dāng)于是一個開關(guān),打開了這個開關(guān)就可以插入想要的值 從父傳 HTML的結(jié)構(gòu) --> <slot>我是默認(rèn)的插槽</slot> </div> </template> <script> export default { name: "goods", data() { return {} } } </script> <style scoped> .son { border: 1px solid red; } </style>
我們先看下我們的實(shí)現(xiàn)效果:
可以看出來,我們的<goods></goods>調(diào)用了四次,我們在父中的值傳到子中的都不一樣,頁面也根據(jù)我們所想的展示出來了不同的組件。
2.具名插槽
使用多個slot實(shí)現(xiàn)精準(zhǔn)的傳遞多個位置的插槽給子組件 ,寫的時候必須在<template></template>中
具名插槽書寫結(jié)構(gòu):
父傳:
<組件名> <template v-slot:自定義名> <h2>HTML結(jié)構(gòu)</h2> </template> </組件名>
子收:
<div > <slot name="自定義插槽名">插槽默認(rèn)值</slot> </div>
我們一起來看看這個例子:
父組件:App02(具名插槽).vue
<template> <div> <h1>我是父組件</h1> <cell> <template v-slot:title> <h2>I am Tittle</h2> </template> <template v-slot:content> <i>I am goodsInfo</i> </template> <template v-slot:right> <i>My position</i> </template> </cell> </div> </template> <script> import cell from '@/components/cell.vue' export default { components:{cell} } </script> <style> </style>
子組件:cell.vue
<template> <div class="cell"> <!-- 具名插槽使用: 1.在子組件鐘使用 slot+name確定組件的作用域 2.在父組件鐘用template 接收 使用v-slot:name傳遞 --> <div class="title" > <slot name="title">我是默認(rèn)標(biāo)題</slot> </div> <div class="content" > <slot name="content"> 我是文本信息</slot> </div> <div class="right" > <slot name="right">我是右側(cè)信息</slot> </div> </div> </template> <script> export default { } </script> <style> .cell{ border: 1px solid #f00; height: 60px; padding: 10px; position: relative; } .title{ float: left; line-height: 1px; } .content{ position: absolute; bottom: 10px; left: 10px; } .right{ float: right; } </style>
實(shí)現(xiàn)效果:
通過這個例子,我們可以看到,我們具名比匿名插槽多了一個精準(zhǔn)定位的功能。
3.作用域插槽
父組件可根據(jù)子組件傳過來的插槽數(shù)據(jù)來進(jìn)行不同的方式展現(xiàn)和填充插槽內(nèi)容
作用域插槽書寫結(jié)構(gòu):
子組件傳遞:
<slot 屬性名="屬性值">默認(rèn)值</slot>
父組件接收:(注意接收的是一個對象)
<組件名 父傳值屬性> <template v-slot="{一個對象}"> HTML屬性 </template> </組件名>
來個例子:
父組件:App03(作用域插槽).vue
<template> <div> <!-- 1.匿名插槽:父組件傳遞 單個HTML結(jié)構(gòu) 給子組件 父傳:<子組件>HTML結(jié)構(gòu)</子組件> 子收:<slot>默認(rèn)HTML結(jié)構(gòu)</slot> 2.具名插槽:父組件傳遞 多個HTML結(jié)構(gòu) 給子組件 父傳: <子組件> <template #插槽名> HTML結(jié)構(gòu) </template> </子組件> 子收:<slot name="插槽名">默認(rèn)HTML結(jié)構(gòu)</slot> 3.作用域插槽:子組件傳遞數(shù)據(jù)給父組件 子傳:<slot 屬性名="屬性值">默認(rèn)HTML結(jié)構(gòu)</slot> 父收: <子組件> <template v-slot="對象名"> HTML結(jié)構(gòu) </template> </子組件> --> <!-- (具名插槽 + 作用域插槽)組合寫法:#插槽名 = "對象名" --> <h1>父組件</h1> <student></student> <h3>刪除功能</h3> <student :arr="list1"> <template v-slot="{ $index }"> <button @click="list1.splice($index, 1)">刪除</button> </template> </student> <h3>頭像功能</h3> <student :arr="list2"> <template v-slot="{ row }"> <img :src="row.headImgUrl" alt="" /> </template> </student> </div> </template> <script> import student from "./components/student.vue"; export default { components: { student }, data() { return { list1: [ { id: "13575", name: "小傳同學(xué)", age: 18, headImgUrl: "http://yun.itheima.com/Upload/./Images/20210303/603f2d2153241.jpg", }, { id: "62408", name: "小黑同學(xué)", age: 25, headImgUrl: "http://yun.itheima.com/Upload/./Images/20210304/6040b101a18ef.jpg", }, { id: "73969", name: "智慧同學(xué)", age: 21, headImgUrl: "http://yun.itheima.com/Upload/./Images/20210302/603e0142e535f.jpg", }, ], list2: [ { id: "13575", name: "傳同學(xué)", age: 8, headImgUrl: "http://yun.itheima.com/Upload/./Images/20210303/603f2d2153241.jpg", }, { id: "62408", name: "黑同學(xué)", age: 5, headImgUrl: "http://yun.itheima.com/Upload/./Images/20210304/6040b101a18ef.jpg", }, { id: "73969", name: "慧同學(xué)", age: 1, headImgUrl: "http://yun.itheima.com/Upload/./Images/20210302/603e0142e535f.jpg", }, ], }; }, }; </script> <style> </style>
子組件: student.vue
<template> <div> <slot name="title" >修改</slot> <table border="1"> <thead> <tr> <th>序號</th> <th>姓名</th> <th>年齡</th> <th>頭像</th> </tr> </thead> <tbody> <tr v-for="(item,index) in arr" :key="item.id"> <td>{{ index+1 }}</td> <td>{{ item.name }}</td> <td>{{ item.age }}</td> <td> <slot :row="item" :$index="index"></slot> </td> </tr> </tbody> </table> </div> </template> <script> export default { props: { arr: Array }, data() { return {} } } </script> <style scoped> table { margin-top: 20px; } td { height: 60px; } img { height: 90%; } </style>
效果如下:
可以看見,我們復(fù)用的三個student的組件都分別實(shí)現(xiàn)了不同的效果,第一個因?yàn)槲覜]有將父組件中的arr傳進(jìn)去,因此arr提示undefin,后面兩個組件分別實(shí)現(xiàn)了不同的功能。對比具名插槽,作用域插槽實(shí)現(xiàn)了
總結(jié)匿名|具名|作用域函數(shù):
匿名插槽:插槽可以實(shí)現(xiàn)組件復(fù)用的同時顯示不同的內(nèi)容
具名插槽:slot開關(guān)可以寫多個,并且可以精準(zhǔn)定位到我們想要的位置
作用域插槽:子組件可以傳遞數(shù)據(jù)給父組件
總結(jié)
到此這篇關(guān)于vue2組件進(jìn)階與插槽詳解的文章就介紹到這了,更多相關(guān)vue2組件進(jìn)階與插槽內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue利用路由鉤子token過期后跳轉(zhuǎn)到登錄頁的實(shí)例
下面小編就為大家?guī)硪黄猇ue利用路由鉤子token過期后跳轉(zhuǎn)到登錄頁的實(shí)例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10vue實(shí)現(xiàn)tab路由切換組件的方法實(shí)例
這篇文章主要給大家介紹了關(guān)于vue實(shí)現(xiàn)tab路由切換組件的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05vue axios數(shù)據(jù)請求及vue中使用axios的方法
axios 是一個基于Promise 用于瀏覽器和 nodejs 的 HTTP 客戶端,在vue中數(shù)據(jù)請求需要先安裝axios。這篇文章主要介紹了vue axios數(shù)據(jù)請求及vue中使用axios的方法,需要的朋友可以參考下2018-09-09vue.js的狀態(tài)管理vuex中store的使用詳解
今天小編就為大家分享一篇vue.js的狀態(tài)管理vuex中store的使用詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-11-11vue路由攔截器和請求攔截器知識點(diǎn)總結(jié)
在本篇文章里小編給各位整理的是一篇關(guān)于vue路由攔截器和請求攔截器知識點(diǎn)總結(jié)文章,有興趣的朋友們學(xué)習(xí)下。2019-11-11Vue利用History記錄上一頁面的數(shù)據(jù)方法實(shí)例
這篇文章主要給大家介紹了關(guān)于Vue利用History記錄上一頁面的數(shù)據(jù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-11-11