Vue — 第四天(components组件)
問題導(dǎo)入
下面的代碼是一個(gè)折疊面板的效果。
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><!-- <script src="./vue.js"></script> --><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script><style>body{background-color: #ccc;}#app{width: 400px;margin: 20px auto;background-color: #fff;border:4px solid blueviolet;border-radius: 1em;box-shadow: 3px 3px 3px rgba(0, 0, 0, .5);padding:1em 2em 2em;}h3{text-align: center;}.title{display: flex;justify-content: space-between;align-items: center;border:1px solid #ccc;padding: 0 1em;}.title h4{line-height: 2;margin:0;}.container{border:1px solid #ccc;padding: 0 1em;}.btn {/* 鼠標(biāo)改成手的形狀 */cursor: pointer;}</style> </head> <body><div id="app"><h3>案例:折疊面板</h3><div><div class="title"><h4>芙蓉樓送辛漸</h4><span class="btn"v-on:click="isVisiable= !isVisiable">{{isVisiable ? '收起' : '展開'}}</span></div><div class="container" v-show="isVisiable">寒雨連江夜入?yún)?#xff0c;<br>平明送客楚山孤。<br>洛陽親友如相問,<br>一片冰心在玉壺。<br></div></div></div><script>const vm = new Vue({el: "#app",data: {isVisiable: true // 表示當(dāng)前 內(nèi)容是否顯示}})</script></body> </html>如何實(shí)現(xiàn)多個(gè)折疊面板
解決方案:
- 復(fù)制代碼
- 代碼重復(fù) 冗余
- 不利于維護(hù)
- 封裝組件
體驗(yàn)組件的使用
代碼如下:
<div id="app"><h2>案例:折疊面板</h2><pannel></pannel><pannel></pannel></div></div><script src="./vue.js"></script><script>var vm = new Vue({el: '#app',components: {pannel: {data(){return {isOpen: false}},template: `<div class="box"><div class="title" ><h4>我是標(biāo)題12</h4><span class="btn" @click="isOpen=!isOpen">{{isOpen ? '收起' : '展開'}} </span> </div><div class="container" v-show="isOpen">我是內(nèi)容<br>我是內(nèi)容</div></div>`}}})</script>vue-devtools
在使用組件的時(shí)候,不好觀察效果,vue官方提供了一個(gè)針對vue項(xiàng)目的調(diào)試工具。
使用效果
安裝
方法一:chrome瀏覽器應(yīng)用商店下載
- https://chrome.google.com/webstore/category/extensions?hl=zh-CN 安裝。
方法二:本地安裝步驟:
1、解壓今天資料中的 vue-devtools.zip 文件,注意:解壓到某個(gè)不會改動的目錄。
2、進(jìn)入chrome瀏覽的擴(kuò)展程序
3、打開開發(fā)者模式
4、加載已解壓的擴(kuò)展程序
用vue-devtools 來觀察上的組件
通過瀏覽器打開使用了vue技術(shù)的網(wǎng)頁
學(xué)習(xí)組件的使用
理解組件
vue組件是可復(fù)用的 Vue 實(shí)例,它可以包含獨(dú)立的HTML結(jié)構(gòu),CSS樣式,JS代碼。它可以把一個(gè)完整的頁面,根據(jù)界面功能拆分成若干組件。
js模塊,獨(dú)立的一個(gè)js文件,提供js邏輯,函數(shù)。
組件底層是什么?
- 組件本質(zhì)上是一個(gè)vue實(shí)例,但是寫法和vue實(shí)例不同,new Vue({//配置對象})
- 在Vue實(shí)例中 new Vue({components:{//組件}})
- 組件有配置對象:
- 不包含 el 選項(xiàng),el是指定vue實(shí)例(或者稱為根組件)管理的視圖容器。
- 通過 template選項(xiàng),指定html結(jié)構(gòu)容器,每個(gè)組件模板有且只有一個(gè)根元素。
- data數(shù)據(jù)項(xiàng)必須是一個(gè)函數(shù),通過它的返回值來設(shè)置數(shù)據(jù)。
- 配置選項(xiàng):data methods watcher filters directives computed created …(創(chuàng)建組件,創(chuàng)建vue實(shí)例)
定義格式
new Vue({el: '#app'data: {},components: {// 組件本質(zhì)上是一個(gè)vue實(shí)例,但是寫法和vue實(shí)例不同組件名1: { data () { return {數(shù)據(jù)項(xiàng)}}, // 必須是一個(gè)函數(shù)template: `<div>模板</div>`, // 約定模板props:[], // 從父組件中獲取數(shù)據(jù)methods:{},watcher:{},filters:{},directives:{},computed:{},created(){},components:{} // 繼續(xù)定義子組件...},組件名2: {data () { return {數(shù)據(jù)項(xiàng)}},template: `<div>模板</div>`,props:[], // 從父組件中獲取數(shù)據(jù)methods:{}...}} })組件本質(zhì)上是一個(gè)vue實(shí)例,但是在寫法上和vue實(shí)例稍有不同:
- 不包含 el 選項(xiàng),el是指定vue實(shí)例(或者稱為根組件)管理的視圖容器。
- 通過 template選項(xiàng),指定html結(jié)構(gòu)容器,每個(gè)組件模板有且只有一個(gè)根元素。
- data數(shù)據(jù)項(xiàng)必須是一個(gè)函數(shù),這個(gè)函數(shù)必須返回一個(gè)對象,在這個(gè)對象中設(shè)置數(shù)據(jù)項(xiàng)。
使用格式
在模板中使用,就像使用dom標(biāo)簽一樣。
<子組件1></子組件1>基本示例
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title> </head> <body><div id="app"><h3>學(xué)習(xí)組件的使用</h3><city-qj></city-qj><br><comp1></comp1><comp1></comp1><br></div><script src="./vue.js"></script><script>// 1. 組件是什么// 組件是可復(fù)用的Vue實(shí)例。// 2. 如何定義// new Vue ({// el:,//// components: {// // 定義組件// // 組件名1 : 對組件的配置項(xiàng),它是一個(gè)對象.// // 在new Vue({ }) 可以寫的配置項(xiàng),在組件中基本上都可以用// comp1: {// // 組件的data與vue實(shí)例有一點(diǎn)區(qū)別:它必須是一個(gè)函數(shù),通過這個(gè)函數(shù)來返回對象,// // 在對象中定義自己的數(shù)據(jù)項(xiàng)// data: function() { // return { // // 組件自己的數(shù)據(jù)項(xiàng)// }// },// // 用來約定組件的模板。它等價(jià)于vue實(shí)例的 el// // 它只能一個(gè)根元素// // template: `<div></div><h1></h1>` // 不ok// template: `<div></div>` // ok// watch:,// computed:,// filters,// directives,// components,// }// }// })// 3. 如何使用// 像使用dom標(biāo)簽一樣使用,標(biāo)簽就是組件名// 要點(diǎn):// 1. 數(shù)據(jù)。// 組件是自成體系,它的數(shù)據(jù)只能自己用,在其它組件不能使用;它不能直接使用vue實(shí)例中的數(shù)據(jù)// 格式:data(){ return {} }// 2. 視圖。由template決定。// 3. methods// 與vue實(shí)例中的一樣,定義,去調(diào)用。// 它只能調(diào)用自己的定義的methodsconst vm = new Vue({el: '#app',data: {name: 'js'},methods: {f1 () {}},components: {"city-qj": {// 定義數(shù)據(jù):只能在當(dāng)前組件中使用data() {return {teC: '小龍蝦'}},// 設(shè)置視圖template: `<div><h4>城市:潛江</h4><p>{{teC}}</p><button @click="hClick">點(diǎn)我</button> </div>`,// 定義方法:只能在當(dāng)前組件中使用methods: {hClick () {// 它的this是組件自己console.log(this.teC)}}},comp1: {template: '<div><h1>comp1組件</h1></div>'}}})</script> </body> </html>組件名和父子組件
<div id="app"><MyComp1></MyComp1><myComp1></myComp1><my-comp1></my-comp1> </div> <script src="./vue.js"></script> <script>new Vue({el: '#app',components: {MyComp1:{template:`<div>子組件:MyComp1 大駝峰</div>`},myComp1:{template:`<div>子組件:myComp1 小駝峰</div>`},mycomp1:{template:`<div>子組件:mycomp1 純小寫</div>`}}}); </script>-
父子組件
- 如果組件A在組件B中被調(diào)用,則稱組件B是組件A的父組件,而組件A是組件B的子組件
-
組件名:
- 在定義組件時(shí),組件名可以是小駝峰(myCom1),大駝峰的寫法(MyCom1)
- 在模板中使用組件時(shí),全采用全小寫的烤串寫法(my-com1)
組件的嵌套
一個(gè)組件內(nèi)部,還可以繼續(xù)定義,使用組件。
<div id="app"><my-comp1></my-comp1> </div> <script src="./vue.js"></script> <script>new Vue({el: '#app',components: {myComp1:{template:`<div>子組件 <abcd></abcd></div>`,components:{abcd:{template:`<h5>ABCD</h5>`}}}}}); </script>小結(jié)
vue中的組件系統(tǒng)讓我們可以像搭積木一樣,通過不同的組件來建立整個(gè)頁面。
父子組件傳值-從數(shù)據(jù)從父組件傳給子組件
基本步驟
-
在父組件中使用子組件時(shí),給子組件傳入自定義屬性;
-
子組件內(nèi)部聲明props來接收屬性。
原則:你情我愿
示例
<div><com1 abc="vue" :myMsg="info"></com1> </div>components:{com1:{template: `<div>子組件:{{myMsg}}</div>`,// props 用來接收使用組件所綁定的屬性數(shù)據(jù),屬性的名字就是數(shù)據(jù)的字段名稱// props: ['abc'] 接收到了使用組件綁定的abc屬性屬性,使用vue實(shí)例即可訪問,this.abc // 此時(shí)的 this.myMsg 其實(shí)就是父組件傳遞給子組件的數(shù)據(jù)props: ['abc','myMsg'] })- 只讀不能修改
- 父組件中修改了值,也會影響子組件中的Props值
案例-折疊面板
<style>body{background-color: #eee;}#app{background-color:#fff;width: 500px;margin: 50px auto;text-align: center;box-shadow: 3px 3px 3px rgba(0 , 0, 0, 0.5);padding:1em 2em;}.title {line-height: 1;display: flex;justify-content: space-between;align-items: center;}.btn{ cursor: pointer;}.container {border: 1px solid #ccc;padding: 1em; }</style> </head> <body><div id="app"><h2>案例:折疊面板</h2><pannel title="標(biāo)題1" content="內(nèi)容1"></pannel><pannel title="標(biāo)題2" content="內(nèi)容2"></pannel></div></div><script src="./vue.js"></script><script>const pannel = {props: ['title','content'],data(){return {isOpen: false}},template: `<div class="box"><div class="title" ><h4>{{title}}</h4><span class="btn" @click="isOpen=!isOpen">{{isOpen ? '收起' : '展開'}} </span> </div><div class="container" v-show="isOpen">{{content}}</div></div>`}var vm = new Vue({el: '#app',components: {pannel: pannel}})</script>組件中的插槽
對于前面的折疊面板組件,如果使用組件時(shí),希望傳入一些比較復(fù)雜的內(nèi)容,讓每個(gè)折疊面板的內(nèi)容區(qū)域都不一樣(不僅是數(shù)據(jù)不同,而是整體結(jié)構(gòu)都不同),則可以使用插槽技術(shù)。
定義格式
在子組件的模板中通過slot預(yù)留出來區(qū)域,充當(dāng)占位符的功能。
template: `其它元素....<slot></slot>其它元素....<slot name="插槽1"></slot>其它元素...<slot name="插槽2"></slot>`如果slot有name屬性,則它是叫具名插槽,否則叫默認(rèn)插槽
技巧: 如果只有一個(gè)插槽,則不需要寫插槽名。
使用格式
在使用子組件時(shí),傳入自定義的內(nèi)容即可。
單個(gè)插槽
如果子組件上只有一個(gè)默認(rèn)插槽。
<子組件><div>任意內(nèi)容....</div></子組件>多個(gè)插槽
如果子組件上定義了多個(gè)插槽,則要對應(yīng)標(biāo)記出slot的名字。
<子組件><div>任意內(nèi)容.將會填充默認(rèn)插槽的位置...</div><div slot='插槽名1'>任意內(nèi)容.將會填充插槽1的位置...</div><div slot='插槽名2'>任意內(nèi)容.將會填充插槽2的位置...</div> </子組件>默認(rèn)插槽使用示例
<div id="app"><com1></com1><com1><h1>我是父組件中來填充默認(rèn)插槽的內(nèi)容</h1></com1> </div> <script>var vm = new Vue({el: '#app',components: {com1: {template: `<div>我是子組件com1,<slot>這里默認(rèn)插件的默認(rèn)內(nèi)容</slot> </div>`}}}) </script>具名插槽使用示例
<div id="app"><com1></com1><com1><h1 slot="slot1">我是父組件中來填充具名插槽的內(nèi)容</h1></com1> </div> <script>var vm = new Vue({el: '#app',components: {com1: {template: `<div>我是子組件com1, <slot>這里默認(rèn)插件的默認(rèn)內(nèi)容</slot> <slot name="slot1"></slot></div>`}}}) </script>案例:用插槽來改進(jìn)折疊面板
允許用戶自行定義折疊面板中content區(qū)域的內(nèi)容。
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="./vue.js"></script><!-- <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> --><style>body{background-color: #ccc;}#app{width: 400px;margin: 20px auto;background-color: #fff;border:4px solid blueviolet;border-radius: 1em;box-shadow: 3px 3px 3px rgba(0, 0, 0, .5);padding:1em 2em 2em;}h3{text-align: center;}.title{display: flex;justify-content: space-between;align-items: center;border:1px solid #ccc;padding: 0 1em;}.title h4{line-height: 2;margin:0;}.container{border:1px solid #ccc;padding: 0 1em;}.btn {/* 鼠標(biāo)改成手的形狀 */cursor: pointer;}</style> </head> <body><div id="app"><h3>案例:折疊面板-插槽</h3><my-pannel tit="標(biāo)題1"><table><tr><td>1</td><td>2</td><td>3</td></tr></table></my-pannel><my-pannel tit="標(biāo)題2"><img src="http://img3m9.ddimg.cn/32/4/28530149-1_w_7.jpg"><!-- 圖片 --></my-pannel><my-pannel tit="標(biāo)題3"><div>寒雨連江夜入?yún)?#xff0c;<br>平明送客楚山孤。<br>洛陽親友如相問,<br>一片冰心在玉壺。<br></div></my-pannel></div><script>// 對于折疊面板:// 特點(diǎn):// - 標(biāo)題一般會比較簡單,所以使用props傳值// - 內(nèi)容可能比較復(fù)雜,通過插槽技術(shù)允許用戶傳入任意內(nèi)容// 由于只需要一個(gè)插槽,所以就直接使用默認(rèn)插槽就行。// 下面是用組件來解決的const vm = new Vue({el: "#app",components: {// 定義的組件的名字MyPannel: {data () {return {isVisiable: true, // 表示當(dāng)前 內(nèi)容是否顯示}},props:['tit'],template: `<div><div class="title"><h4>{{tit}}</h4><span class="btn"v-on:click="isVisiable= !isVisiable">{{isVisiable ? '收起' : '展開'}}</span></div><div class="container" v-show="isVisiable"><slot></slot></div></div>`}}})</script></body> </html>子組件傳值給父組件
背景:
在子組件中需要向父組件傳值
原理
- 自定義事件 + emit
步驟
-
在父組件中:使用子組件時(shí),在子組件上添加自定義事件監(jiān)聽
<子組件 @自定義事件名1="處理事件的函數(shù)1"@自定義事件名2="處理事件的函數(shù)2"></子組件> -
在子組件中:在某個(gè)時(shí)刻,通過$emit向父組件傳遞事件,并附加參數(shù)
this.$emit(自定義事件名1,附加參數(shù))
示例
<div id="app"><comp1 @gameover1="hGameover1" @over="hover"></comp1> </div> methods: {hover (param) {console.log(param)} }, components:{comp1: {template:`<div> <button @click="$emit('gameover')"> 發(fā)消息 </button><button @click="hClick"> 發(fā)消息 </button></button></div>`,methods: {hclick () {this.$emit('over', {a:1,b:2})}}} }案例-測試題
參考代碼:
全局組件
在vue實(shí)例中定義的組件稱為局部組件,它只能當(dāng)前vue實(shí)例中使用;
在vue實(shí)例之外的定義的組件稱為全局組件,它可以在多個(gè)vue實(shí)例中使用,方便封裝組件共享給他人使用。
定義格式
Vue.component('組件名稱','組件配置對象')
這里的組件配置對象與上述局部組件的方法一樣。
使用格式
與局部組件一致。
示例
<div id="app"><!-- 注冊組件時(shí)候使用的組件名稱,在視圖中使用就是自定義標(biāo)簽的名稱 --><!-- 注意:組件的名稱不能和原生html標(biāo)簽重名 --><com-article></com-article></div><script src="./vue.js"></script><script>// 全局注冊組件Vue.component('com-article', {// 組件配置對象,和vue實(shí)例的配置對象基本一致,沒有el選項(xiàng)// template選項(xiàng)必須指定,當(dāng)前組件管理的視圖,需要有一個(gè)根標(biāo)簽。// 在模板字符中,可以使用插值表達(dá)式,和任意指令,但是只能使用當(dāng)前組件數(shù)據(jù)和函數(shù)。template: '<div>{{count}} <button @click="add()">自增1</button></div>',// 聲明數(shù)據(jù),使用的還是data,但是是一個(gè)函數(shù),函數(shù)的返回值才是組件的數(shù)據(jù),必須是對象。data () {return {count: 100}},// 可以使用任意配置選項(xiàng)methods: {add () {this.count ++ }}})// 根實(shí)例const vm = new Vue({el: '#app'})</script>件稱為局部組件,它只能當(dāng)前vue實(shí)例中使用;
在vue實(shí)例之外的定義的組件稱為全局組件,它可以在多個(gè)vue實(shí)例中使用,方便封裝組件共享給他人使用。
定義格式
Vue.component('組件名稱','組件配置對象')
這里的組件配置對象與上述局部組件的方法一樣。
使用格式
與局部組件一致。
示例
<div id="app"><!-- 注冊組件時(shí)候使用的組件名稱,在視圖中使用就是自定義標(biāo)簽的名稱 --><!-- 注意:組件的名稱不能和原生html標(biāo)簽重名 --><com-article></com-article></div><script src="./vue.js"></script><script>// 全局注冊組件Vue.component('com-article', {// 組件配置對象,和vue實(shí)例的配置對象基本一致,沒有el選項(xiàng)// template選項(xiàng)必須指定,當(dāng)前組件管理的視圖,需要有一個(gè)根標(biāo)簽。// 在模板字符中,可以使用插值表達(dá)式,和任意指令,但是只能使用當(dāng)前組件數(shù)據(jù)和函數(shù)。template: '<div>{{count}} <button @click="add()">自增1</button></div>',// 聲明數(shù)據(jù),使用的還是data,但是是一個(gè)函數(shù),函數(shù)的返回值才是組件的數(shù)據(jù),必須是對象。data () {return {count: 100}},// 可以使用任意配置選項(xiàng)methods: {add () {this.count ++ }}})// 根實(shí)例const vm = new Vue({el: '#app'})</script>總結(jié)
以上是生活随笔為你收集整理的Vue — 第四天(components组件)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Vue — 第三天(计算属性和json-
- 下一篇: Vue — 第五天(路由)