1. 程式人生 > >vue 插槽slot與provide/inject跨元件傳值

vue 插槽slot與provide/inject跨元件傳值

vue 插槽slot

1. 預設插槽

const component = {
  template: `
    <div :style="style">
      <slot></slot>
    </div>
  `,
  data () {
    return {
      style: {
        width: '200px',height: '100px',border: '1px solid #aaa'
      }
    }
  }
}

new Vue({
  el: '#root',
  data () {
    return
{ value: '123' } }, template: ` <div> <comp> <span>I am slot</span> </comp> </div> `, components: {Comp: component} }) */

這裡寫圖片描述

2. 具名插槽

const component = {
  template: `
    <div :style="style">
      <div class="header">
        <slot
name="header">
</slot> </div> <div class="body"> <slot name="body"></slot> </div> <div>common footer</div> </div> `, data () { return { style: { width: '200px',height: '100px',border: '1px solid #aaa' } } } } new Vue({ el: '#root', data () { return { value: '123' } }, template: ` <div
>
<comp> <span slot="header">I am header</span> <span slot="body">I am body</span> </comp> </div> `, components: {Comp: component} })

這裡寫圖片描述

3. 作用域插槽

const component = {
  template: `
    <div :style="style">
      <slot :value="value" abc="111"></slot>
    </div>
  `,
  data () {
    return {
      style: {
        width: '200px',height: '100px',border: '1px solid #aaa'
      },
      value: '456'
    }
  }
}

new Vue({
  el: '#root',
  data () {
    return {
      value: '123'
    }
  },
  template: `
  <div>
  <comp ref="comp">
    <span slot-scope="pp" ref="span">{{pp.value}} {{pp.abc}}</span>
  </comp>
  </div>
  `,
  mounted () {
    console.log(this.$refs.comp) // VueComponent物件
    console.log(this.$refs.comp.value) // 456
    console.log(this.$refs.span) // span節點
  },
  components: {Comp: component}
})

這裡寫圖片描述

4.inject provide 子孫元件(跨元件)傳值

onst ChildComp = {
  template: `<div>
    <span>child component</span>
    <span> {{value}}</span>
  </div>`,
  inject: ['grandParent', 'value'],
  mounted () {
    console.log(this.$parent.$options.name) // Vue 物件
    console.log(this.grandParent, this.value) // '123'
  }
}

const component = {
  name: 'comp',
  components: {
    ChildComp
  },
  template: `
    <div>
      <slot :value="value" abc="111"></slot>
      <child-comp></child-comp>
    </div>
  `,
  data () {
    return {
      value: 'component value'
    }
  }
}

new Vue({
  el: '#root',
  data () {
    return {
      value: '123'
    }
  },
  provide () {
    return {
      grandParent: this,
      value: this.value
    }
  },
  template: `
  <div>
  <comp ref="comp">
    <span slot-scope="pp" ref="span">{{pp.value}} {{pp.abc}} {{value}}</span>
  </comp>
  <input v-model="value" >
  </div>
  `,
  components: {Comp: component}
})

這裡寫圖片描述
根元件input用v-model更改value,並不會導致孫元件ChildComp的value值實時更改

5.跨元件的資料繫結

在跟元件的provide中,使用defineProperty,getter獲取value,這樣孫元件ChildComp就能實時獲取到根元件的value,達到v-model的效果

const ChildComp = {
  template: `<div>
    <span>child component : </span>
    <span> {{data.value}}</span>
  </div>`,
  inject: ['grandParent', 'data']
}

const component = {
  name: 'comp',
  components: {
    ChildComp
  },
  template: `
    <div>
      <slot :value="value" abc="111"></slot>
      <child-comp></child-comp>
    </div>
  `,
  data () {
    return {
      value: 'component value'
    }
  }
}

new Vue({
  el: '#root',
  data () {
    return {
      value: '123'
    }
  },
  provide () {
    const data = {}
    Object.defineProperty(data, 'value', {
      get: () => this.value,
      enumerable: true
    })
    return {
      grandParent: this,
      data
    }
  },
  template: `
  <div>
  <comp ref="comp">
    <span slot-scope="pp" ref="span">{{pp.value}} {{pp.abc}} {{value}}</span>
  </comp>
  <input v-model="value" >
  </div>
  `,
  mounted () {
  },
  components: {Comp: component}
})

這裡寫圖片描述