Vue核心知识-Vue的组件之高级属性

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/grapelove01/article/details/82531427

插槽

slot 是 vue 的内置组件。

简单使用

定义一个布局组件,里面放什么会在调用组件时决定,我们不会在布局组件里进行内容设置。在组件标签内部写的内容,可以通过 slot 在组件内部模板中进行使用。

import Vue from 'vue'

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

new Vue({
  components: {
    CompOne: component
  },
  el: '#root',
  data () {
    return {
      value: '123'
    }
  },
  template: `
    <div>
      <comp-one v-model="value">
        <span>this is content</span>
      </comp-one>
    </div>
  `
})

具名插槽

通过 slot 的 name 属性可以指定插入多个内容。

import Vue from 'vue'

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

new Vue({
  components: {
    CompOne: component
  },
  el: '#root',
  data () {
    return {
      value: '123'
    }
  },
  template: `
    <div>
      <comp-one v-model="value">
        <span slot="header">this is content</span>
        <span slot="body">this is body</span>
      </comp-one>
    </div>
  `
})

作用域插槽

scoped slot ,作用域插槽,组件内属性通过作用域插槽传出进行使用。

通常,插槽内使用的属性,使用的是引用组件的组件的属性值。

import Vue from 'vue'

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

new Vue({
  components: {
    CompOne: component
  },
  el: '#root',
  data () {
    return {
      value: '123'
    }
  },
  template: `
    <div>
      <comp-one v-model="value">
        <span>{{value}}t</span>
      </comp-one>
    </div>
  `
})

如果希望插槽模板中使用的属性是组件中的属性时,就用到了 scoped slot

import Vue from 'vue'

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

new Vue({
  components: {
    CompOne: component
  },
  el: '#root',
  data () {
    return {
      value: '123'
    }
  },
  template: `
    <div>
      <comp-one v-model="value">
        <span slot-scope="props">{{props.value}} {{props.aaa}} {{value}}</span>
      </comp-one>
    </div>
  `
})

给组件加 ref

打印结果 this.$refs.comp 是 vue 组件,this.$refs.span 打印出来的是 html 节点,这也是 ref 用在组件和 html 原生标签上的区别

可以通过 $refs 得到组件,进而调用组件的变量和方法,如 this.$refs.comp.value 拿到了组件内部变量 value 值。所以可以通过 ref 操纵组件上的内容(推荐用 props 操纵),除非特殊情况

mounted () {
    console.log(this.$refs.comp, this.$refs.span, this.$refs.comp.value)
  },
  template: `
    <div>
      <comp-one ref="comp">
        <span slot-scope="props" ref="span">{{props.value}} {{props.aaa}} {{value}}</span>
      </comp-one>
    </div>
  `

provide inject越级得实例

$parent 只能到 组件上一级,如果是跨域多级是不行的,通过 provide 和 injection 可以 越级拿到 vue 实例

import Vue from 'vue'

const ChildComponent = {
  template: `<div>child component</div>`,
  inject: ['yeye', 'value'],  // 通过 inject 注入
  mounted () {
    console.log(this.yeye, this.value)  // 在子子组件打印 爷爷实例和数据
  }
}

const component = {
  name: 'comp',
  components: {
    ChildComponent
  },
  template: `
    <div :style="style">
      <slot :value="value" aaa="111"></slot>
      <child-component />
    </div>
  `,
  data () {
    return {
      style: {
        width: '200px',
        height: '200px',
        border: '1px solid #aaa'
      },
      value: 'component value'
    }
  }
}

new Vue({
  components: {
    CompOne: component
  },
  provide () {   // 通过 provide,提供 实例 和 实例的一个属性
    return {
      yeye: this,
      value: this.value
    }
  },
  el: '#root',
  data () {
    return {
      value: '123'
    }
  },
  mounted () {
    console.log(this.$refs.comp, this.$refs.span, this.$refs.comp.value)
  },
  template: `
    <div>
      <comp-one ref="comp">
        <span slot-scope="props" ref="span">{{props.value}} {{props.aaa}} {{value}}</span>
      </comp-one>
    </div>
  `
})

默认情况,provide 不提供 reactive 的属性的,所以我们改 value 的值,子孙组件里 Inject拿到的 value 是不会跟着变的。如果需要改变,需要自己给指定的属性提供 get 方法。这样子孙组件拿到的 data.value 都是通过 get 方法,而 get 方法每次都会获取最新的 value。这个方法比较 hack,可能会被废弃

// 子孙组件
const ChildComponent = {
  template: `<div>child component: {{data.value}}</div>`,
  inject: ['yeye', 'data'],
  mounted () {
    console.log(this.yeye, this.value)
  }
}
// 爷爷组件
provide () {
    const data = {}

    Object.defineProperties(data, 'value', {
      get: () => this.value,
      enumerable: true
    })
    return {
      yeye: this,
      value: this.value
    }
  },

猜你喜欢

转载自blog.csdn.net/grapelove01/article/details/82531427
今日推荐