Vue——自定義組件 & 自定義事件$emit & 插槽slot

一揩懒、注冊(cè)自定義組件

1、局部注冊(cè)

局部注冊(cè)的組件挽封,只能在當(dāng)前Vue實(shí)例中使用已球,并且在其子組件中不可用。
components選項(xiàng)中定義局部組件。每個(gè)組件就是一個(gè)小型的Vue實(shí)例智亮,它里面除了不能設(shè)置el選項(xiàng)忆某,其他選項(xiàng)它都有。
組件名稱:自定義阔蛉,可以使用駝峰命名方式或者短橫線的命名方式弃舒,但是需要注意的是如果應(yīng)用到DOM中,就只能用短橫線命名的方式状原,否則就會(huì)報(bào)錯(cuò)聋呢。注意組件的名稱不要跟原生html元素重名。
template選項(xiàng):定義組件的模板颠区。模板中必須包含一個(gè)根標(biāo)簽削锰。
props選項(xiàng):定義組件標(biāo)簽上的屬性。駝峰命名法的 prop 名(postTitle)需要使用其等價(jià)的短橫線分隔命名法(post-title)命名毕莱。注意:props是只讀的器贩,不能修改(解決辦法:在data中對(duì)props接收到的數(shù)據(jù)進(jìn)行中轉(zhuǎn))。

  • props的值可以是一個(gè)字符串?dāng)?shù)組央串,里面定義每一個(gè)標(biāo)簽屬性名稱磨澡,這是簡單用法,不能對(duì)屬性做嚴(yán)格的驗(yàn)證质和。例如:props:["count"]稳摄。
  • props的值可以是一個(gè)對(duì)象,里面定義每個(gè)標(biāo)簽屬性名稱饲宿,以及對(duì)應(yīng)的類型厦酬。例如:props:{ count:Number }。
  • props的值可以是一個(gè)對(duì)象瘫想,里面定義的每個(gè)標(biāo)簽屬性名稱也可以是一個(gè)對(duì)象仗阅,在這個(gè)對(duì)象里面定義該屬性的完整信息。type 定義類型国夜,required 非空减噪,default 默認(rèn)值。例如:props: {count: { type: Number, required: true, default: 1 } }

data:定義組件的數(shù)據(jù)。注意:Vue實(shí)例的data選項(xiàng)可以是一個(gè)對(duì)象,也可以是一個(gè)方法边琉,由該方法返回一個(gè)對(duì)象和媳。 但是在組件中赶诊,data選項(xiàng)必須是一個(gè)方法,由該方法返回一個(gè)對(duì)象。因?yàn)榻M件可能會(huì)使用很多次,如果data選項(xiàng)是對(duì)象的話抗斤,會(huì)導(dǎo)致多個(gè)組件使用了同一份數(shù)據(jù)囚企。

new Vue({
  el: '#app',
  components: {
       // 自定義組件名
       'component-name': {
         template:`
         <div>
             <p> hello </p>
         </div>
         `,
         props:{ },
         data() {
             return { }
         }       
       }
  }
})
<div id="app">
     <component-name> </component-name>
</div>

2、全局注冊(cè)

全局注冊(cè)的組件可以用在任何新創(chuàng)建的 Vue 根實(shí)例 (new Vue) 的模板中瑞眼。
使用Vue.component來創(chuàng)建全局組件龙宏。Vue.component的第一個(gè)參數(shù)就是組件名。

Vue.component('component-name', {
       template:`
       <div>
           <p> hello </p>
       </div>
       `,
       props:{ },
       data() {
           return { }
       }           
})
new Vue({ el: '#app' })
<div id="app">
     <component-name> </component-name>
</div>

二伤疙、自定義事件 $emit()

$emit()用于觸發(fā)自定義事件烦衣。注意:事件名稱中不能采用大寫字母。

// 觸發(fā)一個(gè)自定義事件掩浙,事件名稱是synccount,將val作為事件對(duì)象傳出去
this.$emit('synccount',val)
<component-name @synccount="synccount(doSomething)"> </component-name>

三秸歧、counter組件

    <div id="app">
        <ul class="list">
            <li v-for="(item,index) in list" :key="index">{{item.label}}--{{item.count}}</li>
        </ul>
        <b-counter v-for="(item,index) in list" :key="index" :label="item.label" :count="item.count"
            @synccount="synccount(index,$event)"></b-counter>
    </div>
        new Vue({
            el: '#app',
            // 定義數(shù)據(jù)
            data: {
                list: [
                    {  label: '衣服',count: 5  },
                    {  label: '褲子',count: 8  },
                    {  label: '鞋子',count: 3  },
                    {  label: '襪子',count: 10  }
                ]
            },
            methods: {
                synccount(index, e) {
                    // 同步更新商品的數(shù)量
                    this.list[index].count = e
                }
            },
            // 注冊(cè)組件
            components: {
                'b-counter': {
                    template: `
                    <div class="counter">
                        <div class="label">{{label}}</div>
                        <div class="btns">
                            <button @click="myCount--" :disabled="myCount===minCount">-</button>
                            <input readonly class="text" type="text" :value="myCount">
                            <button @click="myCount++" :disabled="myCount===maxCount">+</button>
                        </div>
                    </div>
                    `,
                    //props選項(xiàng)
                    props: {
                        // 文本
                        label: {
                            type: String,
                            // 允許為空
                            required: false,
                        },
                        // 數(shù)量
                        count: {
                            type: Number,
                            // 非空
                            required: true
                        },
                        // 最大值
                        maxCount: {
                            type: Number,
                            default: 999
                        },
                        // 最小值
                        minCount: {
                            type: Number,
                            default: 1
                        }
                    },
                    //定義數(shù)據(jù)
                    data() {
                        return {
                            // 將props接收到的count厨姚,中轉(zhuǎn)給myCount
                            myCount: this.count
                        }
                    },
                    // 監(jiān)聽器
                    watch: {
                        // 偵聽myCount是否發(fā)生變化
                        myCount(val) {
                            // 觸發(fā)一個(gè)自定義事件synccount,將count的最新值作為事件對(duì)象傳出去
                            this.$emit('synccount', val)
                        }
                    }
                }
            }
        })

效果:

四键菱、評(píng)分組件

    <div id="app">
        <ul class="list">
            <li v-for="(item,index) in list" :key="index">{{item.title}}--{{item.value}}</li>
        </ul>
        <b-star v-for="(item,index) in list" :key="index" 
        :title="item.title" :value="item.value" @syncvalue="syncvalue(index,$event)"></b-star>
    </div>
        // 注冊(cè)全局組件
        Vue.component('b-star', {
            //模板
            template:`
            <div class="star">
                <div class="title">{{title}}</div>
                <div>
                    <i v-for="item in 10" :key="item" class="iconfont" 
                    :class="item<=myValue?'icon-xingxing':'icon-star'"
                    @mouseenter="enter(item)" @mouseleave="leave(item)" @click="okValue=item"></i>
                </div>
            </div>
            `,
            // 定義組件的標(biāo)簽屬性
            props:{
                title:{
                    type:String,
                    required:false
                },
                value:{
                    type:Number,
                    default:0
                }
            },
            // 數(shù)據(jù)
            data() {
                return {
                    // 中轉(zhuǎn)props傳進(jìn)來的value值
                    myValue:this.value,
                    // 定義一個(gè)確定值
                    okValue:this.value
                }
            },
            // 方法
            methods: {
               // 鼠標(biāo)進(jìn)入時(shí)谬墙,調(diào)用的方法
                enter(val){
                    this.myValue = val
                },
               // 鼠標(biāo)離開時(shí),調(diào)用的方法
                leave(val){
                    this.myValue = this.okValue
                }
            },
            // 監(jiān)聽器
            watch:{
                // 偵聽okValue的變化
                okValue(val){
                    // 觸發(fā)自定義事件
                    this.$emit('syncvalue',val)
                }
            }
        })
        new Vue({
            el:'#app',
            data:{
                list:[
                    {
                        title:'產(chǎn)品質(zhì)量',
                        value:5
                    },
                    {
                        title:'物流速度',
                        value:7
                    },
                    {
                        title:'客服態(tài)度',
                        value:2
                    }
                ]
            },
            methods: {
                // 同步評(píng)分
                syncvalue(index,e){
                    this.list[index].value = e
                }
            },
        })

效果:

五经备、組件中的插槽

slot 用于在組件的內(nèi)部定義插槽拭抬,組件標(biāo)簽之間的所有html內(nèi)容,會(huì)在插槽所在位置呈現(xiàn)侵蒙。

    <div id="app">
        <b-tab :list="list" :active="activeIndex">
            <h2>全國著名小吃</h2>
        </b-tab>
    </div>
        Vue.component('b-tab', {
            template: `
            <div class="tab">
                <slot></slot>
                <ul class="titles">
                    <li @click="activeIndex=index" :class="{active:activeIndex===index}" v-for="(item,index) in list" :key="index">{{item.title}}</li>
                </ul>
                <ul class="contents">
                    <li v-show="activeIndex===index" v-for="(item,index) in list" :key="index">{{item.content}}</li>
                </ul>
            </div>
            `,
            props: ['list', 'active'],
            data() {
                return {
                    activeIndex: this.active
                }
            }
        })
        new Vue({
            el: '#app',
            data: {
                // 高亮索引
                activeIndex: 0,
                list: [
                    {
                        title: '北京',
                        content: '北京的糖葫蘆真好吃'
                    },
                    {
                        title: '南京',
                        content: '南京的鹽水鴨真好吃'
                    },
                    {
                        title: '武漢',
                        content: '武漢的熱干面真好吃'
                    },
                    {
                        title: '長沙',
                        content: '長沙的臭豆腐真好吃'
                    }
                ]
            }
        })

效果:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末造虎,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子纷闺,更是在濱河造成了極大的恐慌算凿,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件犁功,死亡現(xiàn)場離奇詭異氓轰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)浸卦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門署鸡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人限嫌,你說我怎么就攤上這事靴庆。” “怎么了萤皂?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵撒穷,是天一觀的道長。 經(jīng)常有香客問我裆熙,道長端礼,這世上最難降的妖魔是什么禽笑? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮蛤奥,結(jié)果婚禮上佳镜,老公的妹妹穿的比我還像新娘。我一直安慰自己凡桥,他們只是感情好蟀伸,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缅刽,像睡著了一般啊掏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上衰猛,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天迟蜜,我揣著相機(jī)與錄音,去河邊找鬼啡省。 笑死娜睛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的卦睹。 我是一名探鬼主播畦戒,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼结序!你這毒婦竟也來了障斋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤笼痹,失蹤者是張志新(化名)和其女友劉穎配喳,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凳干,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晴裹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了救赐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涧团。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖经磅,靈堂內(nèi)的尸體忽然破棺而出泌绣,到底是詐尸還是另有隱情,我是刑警寧澤预厌,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布阿迈,位于F島的核電站,受9級(jí)特大地震影響轧叽,放射性物質(zhì)發(fā)生泄漏苗沧。R本人自食惡果不足惜刊棕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望待逞。 院中可真熱鬧甥角,春花似錦、人聲如沸识樱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽怜庸。三九已至当犯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間割疾,已是汗流浹背灶壶。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留杈曲,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓胸懈,卻偏偏與公主長得像担扑,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子趣钱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容