Vue基础精讲 —— Vue的组件之组件的定义、继承、自定义双向绑定、高级属性

Vue组件基础定义

import Vue from 'vue'

const compoent = {
  props: {
    active: {
      // type: Boolean,
      // required: true,
      validator (value) {
        return typeof value === 'boolean'
      }
    },
    propOne: String
  },
  template: `
    <div>
      <input type="text" v-model="text">
      <span @click="handleChange">{{propOne}}</span>
      <span v-show="active">see me if active</span>
    </div>
  `,
  data () {
    return {
      text: 0
    }
  },
  methods: {
    handleChange () {
      this.$emit('changeY')
    }
  }
}

// Vue.component('CompOne', compoent)

new Vue({
  components: {
    CompOne: compoent
  },
  data: {
    prop1: 'test'
  },
  methods: {
    handleChange () {
      this.prop1 = this.prop1 + ' test'
    }
  },
  mounted () {
    console.log(this.$refs.comp1)
  },
  el: '#root',
  template: `
    <div>
      <p>{{prop1}}</p>
      <!--建议传递参用下划线命名,接收参数用驼峰-->
      <!--若传参是非string,需用:-->
      <!--@changeY="handleChange"接收子组件派发的change事件,这里不能@change-y="handleChange"这么写-->
      <comp-one ref="comp1" :active="true" :prop-one="prop1" @changeY="handleChange"></comp-one>
      <comp-one :active="true" propOne="text2"></comp-one>
    </div>
  `
})

Vue组件继承 

import Vue from 'vue'

const compoent = {
  props: {
    active: Boolean,
    propOne: String
  },
  template: `
    <div>
      <input type="text" v-model="text">
      <p @click="handleChange">propOne参数:{{propOne}}</p>
      <p v-show="active">see me if active</p>
    </div>
  `,
  data () {
    return {
      text: 0
    }
  },
  mounted () {
    console.log('compoent1 comp mounted')
  },
  methods: {
    handleChange () {
      this.$emit('change')
    }
  }
}

const componet2 = {
  extends: compoent, // 继承compoent
  data () {
    return {
      text: 1
    }
  },
  mounted () {
    console.log('componet2', this.$parent.$options.name)
  }
}

// const CompVue = Vue.extend(compoent)

// new CompVue({
//   el: '#root',
//   propsData: {
//     propOne: 'xxx'
//   },
//   data: {
//     text: '123'
//   },
//   mounted () {
//     console.log('instance mounted')
//   }
// })

const parent = new Vue({
  name: 'parent'
})

new Vue({
  parent: parent, // 设置父组件
  name: 'Root',
  el: '#root',
  mounted () {
    console.log('Root', this.$parent.$options.name)
  },
  components: {
    Comp: componet2
  },
  data: {
    text: '组件1'
  },
  methods: {
    change () {
      console.log('kkkkk')
    }
  },
  template: `
    <div>
      <span>{{text}}</span>
      <comp propOne="propOne" @change="change"></comp>
    </div>
  `
})

组件继承的执行顺序 

Vue自定义组件双向绑定

import Vue from 'vue'

const component = {
  // 使用model
  model: {
    // prop,子组件接收父组件通过v-model传递过来的值,可重命名为value22
    prop: 'value22',
    // event,该组件在派发emit 'change' 事件的时候,传递参数的值就是父组件v-model能够收到的值。
    event: 'change'
  },
  props: ['value22'], // model中得到的prop值
  template: `
    <div>
      <!--:value为props的值-->
      <input type="text" @input="handleInput" :value="value22">
    </div>
  `,
  methods: {
    handleInput (e) {
      // change为model中的event
      this.$emit('change', e.target.value)
    }
  }
  // 若不使用model接收父组件传参
  // props: ['value'], // 必须要使用value
  // template: `
  //   <div>
  //     <!--:value为props的值-->
  //     <input type="text" @input="handleInput" :value="value">
  //   </div>
  // `,
  // methods: {
  //   handleInput (e) {
  //     // 这儿必须用input发送数据,发送的数据会被父级v-model接收
  //     this.$emit('input', e.target.value)
  //   }
  // }
}

new Vue({
  components: {
    CompOne: component
  },
  el: '#root',
  data () {
    return {
      value11: '123'
    }
  },
  template: `
    <div>
      <!--将父组件数据通过v-model传递给子组件-->
      <comp-one v-model="value11"></comp-one>
    </div>
  `
})

Vue组件高级属性 

import Vue from 'vue'

const ChildComponent = {
  template: '<div>child component: {{data.value}}</div>',
  inject: ['yeye', 'data'], // 跨级组件沟通
  mounted () {
    // console.log(this.yeye, this.value)
  }
}

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

new Vue({
  components: {
    CompOne: component
  },
  provide () {
    const data = {}

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

    return {
      yeye: this,
      data
    }
  },
  el: '#root',
  data () {
    return {
      value: '123'
    }
  },
  mounted () {
    console.log(this.$refs.comp.value, this.$refs.span)
    // 打印vue实例,dom节点,ref用在组件和原生HTML上的区别
  },
  template: `
    <div>
      <comp-one ref="comp">
        <div slot-scope="props" ref="span">
          <P>子组件组件内部变量:{{props.value}} {{props.aaa}}</P>
          <P>当前组件变量:{{value}}</P>
        </div>
      </comp-one>
      <input type="text" v-model="value" />
    </div>
  `
})
// 匿名插槽
// 具名插槽
// 作用域插槽,父组件可使用子组件中的数据slot-scope

与君共勉:再牛逼的梦想,也抵不住傻逼般的坚持!

猜你喜欢

转载自blog.csdn.net/qq_32614411/article/details/81746005