Vue-元件(2)

東方來客發表於2018-09-09

元件通訊

自定義事件

Vue有一套與JS觀察者模式類似的設計,子元件用$emit()來觸發事件,父元件用$on()來監聽子元件的事件。

<div id='app'>
    <son-component @change='handleTotal'></son-component>
    <!--change就是自定義事件-->
</div>
複製程式碼
Vue.component('son-component',{
    template:
    '<div>\
        <button @click='handleIncrease'>+1</button>\
        <button @click='handleReduce'>-1</button>\
    </div>',
    data:function(){
        return {
            count: 0
        }
    },
    methods:{
        handleIncrease:function(){
            this.count += 1;
            this.$emit('change',this.count)
        },
        handleReduce:function(){
            this.count -= 1;
            this.$emit('change',this.count)
        }
    }
})
var app = new Vue({
    el:'#app',
    data:{
        total: 0
    },
    methods:{
        handleTotal:function(value){
            this.total = value
        }    
    }
})
複製程式碼

在元件中使用v-model

<div id="app">
    <son-component v-model='total'></son-component>
</div>
複製程式碼
Vue.component('son-component',{
  template:'<div>\
  <button @click="handleIncrease">+1</button>\
  </div>',
  methods:{
    handleIncrease:function(){
      this.count +=1
      this.$emit('input',this.count)
    }
  },
  data:function(){
    return {
      count:1
    }
  }
})
var app = new Vue({
  el:'#app',
  data:{
    total: 1
  }
})
複製程式碼

非父元件的通訊

  <div id="app">
    <component-a ref='a'></component-a>
    <component-b ref='b'></component-b>
    <hr style="background-color:cyan;height:4px;">
    <component-c ref='c'></component-c>{{msg}}
    <button @click='getChildData'>我是父元件的按鈕,我要拿到子元件的內容</button>
    {{formChild}}
  </div>
複製程式碼
Vue.component('component-a', {
  template: '<div><button @click="handle">我是a元件的按鈕</button></div>',
  data: function () {
    return {
      a: '其實我是a元件的data定義的內容,我通過b中的函式顯示出來。',
      msg: '我是a中的msg'
    }
  },
  methods: {
    handle: function () {
      this.$root.bus.$emit('eve', this.a) //eve為自定義的事件名,this.a是要傳送的資料
    }
  }
})

Vue.component('component-b', {
  template: '<div>其實我是B元件</div>',
  data: function () {
    return {
      msg: '我是b中的msg'
    }
  },
  created: function () {
    this.$root.bus.$on('eve', function (value) {
      alert(value)
    })
  }
})

Vue.component('component-c', {
  template: '<button @click="amend">點我修改父元件的內容</button>',
  data: function () {
    return {
      msg: '我是c中的msg'
    }
  },
  methods: {
    amend: function () {
      this.$parent.msg = '豬突猛進'
    }
  }
})
var app = new Vue({
  el: '#app',
  data: {
    bus: new Vue(),
    msg: '我是未修改過的父元件的內容',
    formChild: '還未拿到'
  },
  methods: {
    //用來拿子元件中的內容
    getChildData: function () {
      this.formChild = this.$refs.b.msg;
    }
  }
})
複製程式碼

插槽

單個slot

<div id="app">
    <part-component>
    {{msg}}
    </part-component>
</div>
複製程式碼
var app = new Vue({
  el:"#app",
  data:{
    msg:'我愛你'
  },
  components:{
    "part-component":{
    template:'\
        <div>你愛我嗎?\
            <slot>你要是不愛我我就出來再問你一遍。</slot>\
        </div>'
    }
  }
})
複製程式碼

使用{{msg}}渲染時:

Vue-元件(2)
不渲染內容則預設顯示<slot>標籤中的內容:

Vue-元件(2)

具名插槽

<div id="app">
    <part-component>
        <h1 slot='head'>1</h1>
        <h2>2</h2>
        <h3>3</h3>
    </part-component>
</div>
複製程式碼
var app = new Vue({
  el: "#app",
  data: {

  },
  components: {
    "part-component": {
      template: '\
            <div>\
                <div class="head">\
                  <slot name="head"></slot>\
                </div>\
                <div class="container">\
                  <slot></slot>\
                </div>\
            </div>',
    }
  }
})
複製程式碼

template中<slot>標籤中定義的name值會自動匹配html標籤中slot屬性值相同的屬性;template中未定義name值的<slot>標籤會去匹配沒有設定slot屬性的標籤,從而改變其dom結構。從而更新資料變得方便。

作用域插槽

作用是通過slot從子元件獲取資料。

  <div id="app">
    <my-component>
      <template slot='name' slot-scope="variable">  
        <!-- variable是一個臨時變數名 -->
        {{variable}}
        <!--渲染出的標籤屬性可以以{{variable.xx}}方式渲染到html-->
      </template>
    </my-component>
  </div>
複製程式碼
    Vue.component('my-component',{
      template:'\
      <div>\
        <slot class="hh" id="qq" qwe="123" text="我是要被拿到的資料" name="name"></slot>\
      </div>'
    })
    var app = new Vue({
      el:'#app',
      data:{
        
      }
    })
複製程式碼

訪問slot插槽

Vue.component('name-component', {
  template: '<div>\
    <div class="header"> \
      <slot name="header"></slot> \
    </div>   \
    <div class="container">  \
      <slot></slot>   \
    </div>  \
    <div class="footer">  \
      <slot name="footer"></slot>  \
     </div>   \
  </div>',
  mounted: function () {
    var head = this.$slots.header;
    console.log(head[0].elm.innerHTML)  //這樣便能獲取到插槽類名為header的內容
  }
})
複製程式碼

動態元件

  <div id="app">
    <component :is='thisView'></component>
    <button @click="dispose('a')">1</button>
    <button @click="dispose('b')">2</button>
    <button @click="dispose('c')">3</button>
    <button @click="dispose('d')">4</button>
  </div>
複製程式碼
Vue.component('component-a',{
      template:'<div>哈哈</div>'
    })
    Vue.component('component-b',{
      template:'<div>嘿嘿</div>'
    })
    Vue.component('component-c',{
      template:'<div>嗯嗯</div>'
    })
    Vue.component('component-d',{
      template:'<div>啵啵</div>'
    })
    var app = new Vue({
      el:'#app',
      data:{
        thisView:'component-a'
      },
      methods:{
        dispose:function(tag){
          this.thisView = 'component-' + tag;
        }
      }
    })
複製程式碼

Vue-元件(2)

相關文章