第4章 深入理解Vue組件

4-1 使用組件細節(jié)點

1.is的使用
當我們寫循環(huán)組件的時候翩瓜,經常給
table中的tr
select中的option
ul中的li或者ol中的li
等等定義組件的時候酿联,我們經常用is來定義組件的名稱酥馍,為了讓瀏覽器成功的渲染正確的dom結構

<div id="root">
    <table>
        <tbody>
        <tr is="row"></tr>
        <tr is="row"></tr>
        <tr is="row"></tr>
        </tbody>
    </table>
    <select name="" id="">
        <option is="selectOption"></option>
        <option is="selectOption"></option>
        <option is="selectOption"></option>
    </select>
    <ul>
        <li is="ulLi"></li>
        <li is="ulLi"></li>
        <li is="ulLi"></li>
    </ul>
</div>
<script>
    Vue.component('row', {
        template: '<tr><td>this is a row</td></tr>'
    });
    Vue.component('selectOption',{
        template: '<option>this is option</option>'
    });
    Vue.component('ulLi',{
        template: '<li>this is li</li>'
    });
    var app = new Vue({
        el: '#root',
        data: {},
    })
</script>

2.在子組件定義data的時候坦喘,必須是一個函數(shù),而不能是一個對象蛋济,返回一個對象是為了每個子組件都能擁有一個獨立的數(shù)據(jù)存儲渤早。這樣子組件之間的數(shù)據(jù)不會互相影響
而在根組件中,data可以是一個對象瘫俊。

<div id="root">
    <table>
        <tbody>
        <tr is="row"></tr>
        <tr is="row"></tr>
        <tr is="row"></tr>
        </tbody>
    </table>
</div>
<script>
    Vue.component('row', {
        data: function () {//返回的是一個函數(shù)
            return {
                content: 'this is row'
            }
        },
        template: '<tr><td>{{content}}</td></tr>'
    });
    var app = new Vue({
        el: '#root',
        data: {}
    })
</script>

3.有時候我們在開發(fā)過程中鹊杖,因為一些業(yè)務的需求悴灵,少不了對dom的操作,那么我們就可以借助ref來實現(xiàn)

//實例一
<div id="root">
    <div ref="hello" @click="handleClick">hello world</div>
</div>
<script>
    var app = new Vue({
        el: '#root',
        data: {},
        methods: {
            handleClick: function () {
                console.log(this.$refs.hello.innerHTML);//通過refs屬性 獲取當前節(jié)點的文本
            }
        }
    });
</script>


//案例二 counter求和
<div id="root">
    <counter ref="one" @change="handleChange"></counter>
    <counter ref="two" @change="handleChange"></counter>
    <div>{{total}}</div>
</div>
<script>
    Vue.component('counter', {
        data: function () {
            return {
                number: 0
            }
        },
        template: '<div @click="handleClick">{{number}}</div>',
        methods: {
            handleClick: function () {
                this.number++;
                this.$emit('change');//觸發(fā)一個監(jiān)聽器
            }
        }
    });
    var app = new Vue({
        el: '#root',
        data: {
            total: 0
        },
        methods: {
            handleChange: function () {
                this.total = this.$refs.one.number + this.$refs.two.number //通過refs 來回去組件的值
            }
        }
    });
</script>
4-2父子組件之間的數(shù)據(jù)傳遞

父組件向子組件傳值:是通過屬性的方式
子組件向父組件傳值:可以通過$emit來觸發(fā)一個事件

vue數(shù)據(jù)傳遞遵循的是單向數(shù)據(jù)流骂蓖,
所以在下面的案例中我們并沒有對content數(shù)據(jù)直接進行數(shù)據(jù)的累加积瞒,而是把content數(shù)據(jù)賦值給了number,對number進行數(shù)據(jù)的累加操作登下。

<div id="root">
    <counter :content="1" @inc="handleInc"></counter><!--父組件通過屬性向子組件傳值-->
    <counter :content="3" @inc="handleInc"></counter>
    <div>{{total}}</div>
</div>
<script>
    Vue.component('counter', {
        props: ['content'],
        data: function () {
            return {
                number: this.content //遵循單向數(shù)據(jù)流
            }
        },
        template: '<div @click="handleClick">{{number}}</div>',
        methods: {
            handleClick: function () {
                this.number += 2;
                //子組件通過方法向父組件傳值
                this.$emit('inc', 2);
            }
        }
    });
    var app = new Vue({
        el: '#root',
        data: {
            total: 4
        },
        methods: {
            handleInc: function (step) {
                this.total += step
            }
        }
    })
</script>
4-3組件參數(shù)校驗和非props特性

1.組件的的參數(shù)校驗

<div id="root">
    <child content="hello"></child>
</div>
<script>
    Vue.component('child', {
        props: {
            content: {
                type: String,
                required: true,
                default: 'default Value',
                validator: function (value) {
                    return (value.length > 5)
                }
            }
        },
        template: '<div>{{content}}</div>'
    });
    var app = new Vue({
        el: '#root',
    })
</script>

2.props特性和非props特性的對比
props特性:
父組件傳遞屬性茫孔,子組件要接受該屬性
props屬性不會顯示在dom的標簽之中
非props特性:
父組件傳遞屬性,子組件沒有去接受被芳,而是直接調用
props屬性會顯示在dom的標簽之中

4-4給組件綁定原生事件

通過.native屬性來綁定原生事件

<div id="root">
    <child @click.native="handleClick"></child>
</div>
<script>
    Vue.component('child', {
        template: '<div>child</div>'
    })
    var app = new Vue({
        el: '#root',
        methods: {
            handleClick: function () {
                console.log('click');
            }
        }
    })
</script>
4-5 非父子組件間的傳值
非父子組件間的傳值

1.通過vuex
2.通過發(fā)布訂閱模式(Bus/總線/發(fā)布訂閱模式/觀察者模式/)

<div id="root">
    <child content="sunny"></child>
    <child content="fan"></child>
</div>
<script>
    Vue.prototype.bus = new Vue();//定義bus
    Vue.component('child', {
        data: function () {
            return {
                newContent: this.content //保證單向數(shù)據(jù)流
            }
        },
        props: {
            content: String
        },
        template: '<div @click="handleClick">{{newContent}}</div>',
        methods: {
            handleClick: function () {
                this.bus.$emit('change', this.newContent); //在bus上發(fā)布一個事件缰贝,并且傳值
            }
        },
        mounted: function () {//通過這個鉤子,來監(jiān)聽change的變化畔濒,通過回調拿到相對應的的值
            var that = this;
            this.bus.$on('change', function (msg) {
                console.log(msg)
                that.newContent = msg//this 指向發(fā)生變更剩晴,所以上面要從新獲取一下this的指向
            })
        }
    });
    var app = new Vue({
        el: '#root'
    })

4-6 在vue中使用插槽

插槽只能有一個
而劇名插槽可以有多個

  <div id="root">
    <body-content>
      <p slot="header">this is header</p>
      <p slot="footer">this is footer</p>
    </body-content>
  </div>
  <script>
    Vue.component('body-content',{
      template:
      `<div>
        <slot name="header">default header</slot> //設置默認值
        <p>this is content</p>
        <slot name="footer"></slot>
      </div>`
    })
    var app = new Vue({
      el:'#root'
    })
  </script>
4-7作用域插槽

父組件調用子組件的時候,給子組件傳了一個插槽侵状,這個插槽是一個作用域的插槽赞弥,這個插槽必須是一個<template slot-scope="props">{{props.item}}</template>
那什么時候使用作用插槽呢?
1.當子組件做循環(huán)
2.或者當子組件的dom結構由外部傳遞進來趣兄,或者有外部決定的時候

<div id="root">
    <child>
      <template slot-scope="props">
        <li>{{props.item}}</li>
      </template>
    </child>
  </div>
  <script>
    Vue.component('child', {
      data: function () {
        return {
          list: [1, 2, 3, 4]
        }
      },
      template: `<div>
        <ul>
          <slot v-for="item of list" :item=item></slot>
        </ul>
      </div>`
    })
    var app = new Vue({
      el: '#root'
    })
  </script>

4-8 動態(tài)組件和v-once 指令
<div id="root">
    <component :is="type"></component> <!--這就是動態(tài)組件-->
    <child-one v-if="type==='child-one'"></child-one>
    <child-two v-if="type==='child-two'"></child-two>
    <button @click="hanleBtnClick">change</button>
  </div>
  <script>
    Vue.component('child-one', {
      template: '<div v-once>child-one</div>'
    })

    Vue.component('child-two', {
      template: '<div v-once>child-two</div>'
    })

    var app = new Vue({
      el: '#root',
      data: {
        type: 'child-one'
      },
      methods: {
        hanleBtnClick: function () {
          this.type = this.type === 'child-one' ? 'child-two' : 'child-one'
        }
      }
    })
  </script>

更多

上一篇:第3章 Vue 基礎精講
下一篇:第5章 Vue 表單
全篇文章:Vue學習總結
所有章節(jié)目錄:Vue學習目錄

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末绽左,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子艇潭,更是在濱河造成了極大的恐慌拼窥,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蹋凝,死亡現(xiàn)場離奇詭異鲁纠,居然都是意外死亡,警方通過查閱死者的電腦和手機仙粱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來彻舰,“玉大人伐割,你說我怎么就攤上這事∪谢剑” “怎么了隔心?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長尚胞。 經常有香客問我硬霍,道長,這世上最難降的妖魔是什么笼裳? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任唯卖,我火速辦了婚禮粱玲,結果婚禮上,老公的妹妹穿的比我還像新娘拜轨。我一直安慰自己抽减,他們只是感情好,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布橄碾。 她就那樣靜靜地躺著卵沉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪法牲。 梳的紋絲不亂的頭發(fā)上史汗,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機與錄音拒垃,去河邊找鬼停撞。 笑死,一個胖子當著我的面吹牛恶复,可吹牛的內容都是我干的怜森。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼谤牡,長吁一口氣:“原來是場噩夢啊……” “哼副硅!你這毒婦竟也來了?” 一聲冷哼從身側響起翅萤,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤恐疲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后套么,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體培己,經...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年胚泌,在試婚紗的時候發(fā)現(xiàn)自己被綠了省咨。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡玷室,死狀恐怖零蓉,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情穷缤,我是刑警寧澤敌蜂,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站津肛,受9級特大地震影響章喉,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一秸脱、第九天 我趴在偏房一處隱蔽的房頂上張望落包。 院中可真熱鬧,春花似錦撞反、人聲如沸妥色。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嘹害。三九已至,卻和暖如春吮便,著一層夾襖步出監(jiān)牢的瞬間笔呀,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工髓需, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留许师,地道東北人。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓僚匆,卻偏偏與公主長得像微渠,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子咧擂,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內容