Vue组件基础

1. provide/inject:两个要组合使用,provide使用的父级组件,inject用在子孙组件,功能相当于React的Context。

因为要使用template属性,所以使用import Vue from 'vue/dist/vue.esm',没用使用import Vue from 'vue';

levelTwo要写在levelOne的前面;

当provide的值是json对象时,无法获取this的值,要写成函数形式才能得到this的值,

通过provide/inject得到的数据不具有reactive的特性,就下面的例子来说,provide提供的值是

    {
      name:"Jack",
      age:18
    } 

根组件再怎么修改age的值,LevelTwo组件的age值永远是18,不会改变,意思就是说,通过这种方式传递的值是不会放生变化的,但是,可以这样做,比如:data的值{name:"Jack",age:18},data的值其实是json对象的地址,意思就是data的值是一个地址,不能改变,但是可以修改地址中存放数据的内容。

import Vue from 'vue/dist/vue.esm'

const levelTwo={
  inject:['name','age'],
  template:`
  <div>
    <div>I am levelTwo</div>
    <div>This is the data from root:{{name}},{{age}}</div>
  </div>`
}

const levelOne={
  name: 'comp',
  components:{
    levelTwo:levelTwo
  },
  template:`
  <div>
    <div>I am levelOne</div>
    <levelTwo />
  </div>`
}


new Vue({
  components:{
    levelOne
  },
  provide:function(){
    return{
      name:"Jack",
      age:this.age
    } 
  },
  template:`
  <div>
    <level-one />
    <input type="text" v-model="age" /> 
    <div>根组件age:{{age}}</div>
  </div>`,
  data:function(){
    return {
      age: 18
    }
  }
}).$mount('#app')

将provide/inject方式得到的值具有reactive性能

import Vue from 'vue/dist/vue.esm'

const levelTwo={
  inject:['name','data'],
  template:`
  <div>
    <div>I am levelTwo</div>
    <div>This is the data from root:{{name}},{{data.age}}</div>
  </div>`
}

const levelOne={
  name: 'comp',
  components:{
    levelTwo:levelTwo
  },
  template:`
  <div>
    <div>I am levelOne</div>
    <levelTwo />
  </div>`
}


new Vue({
  components:{
    levelOne
  },
  provide:function(){
    const data = {}

    Object.defineProperty(data, 'age', {
      get: () => this.age,
      enumerable: true
    })
    return{
      name:"Jack",
      data:data
    } 
  },
  template:`
  <div>
    <level-one />
    <input type="text" v-model="age" /> 
    <div>根组件age:{{age}}</div>
  </div>`,
  data:function(){
    return {
      age: 18
    }
  }
}).$mount('#app')

2. slot

import Vue from 'vue/dist/vue.esm'
//import App from './App.vue'


Vue.config.productionTip = false;



const levelOne={
  name: 'comp',
  template:`
  <div>
    <slot name="header"/>
    <div>This is body</div>
    <slot name="footer" />
  </div>`
}


new Vue({
  components:{
    levelOne
  },
  template:`
  <div>
    <level-one>
      <div slot="header">This is slot content: header</div>
      <div slot="footer">This is slot content: footer</div>
    </level-one>
  </div>`,

}).$mount('#app')

在slot中使用变量

可以使用props,在slot标签上的内容的全部props赋值给slot-scope="props111"中的props111变量,习惯将props111写成props。

slot中的变量,是指slot在定义时所在的组件中的变量。如果想使用其它组件的数据,可以通过props的方式。

显示的内容依次是123 abc 18

import Vue from 'vue/dist/vue.esm'

const levelOne={
  name: 'comp',
  data:function(){
    return{
      value:'abc'
    }
  },
  template:`
  <div>
    <slot :value='value' age="18" ></slot>
  </div>`
}


new Vue({
  components:{
    levelOne
  },
  data:function(){
    return{
      value:123
    }
  },
  template:`
  <div>
    <level-one>
      <div slot-scope="props111">{{value}} {{props111.value}} {{props111.age}}</div>
    </level-one>
  </div>`,

}).$mount('#app')

3. render

在了解render属性之前,先了解一下原生事件和自定义事件,原生事件就是原生DOM上绑定的事件,自定义事件就是组件标签上定义的事件,组件标签上的自定义事件,必须由$emit()触发

import Vue from 'vue/dist/vue.esm'

const levelOne={
  name: 'comp',
  data:function(){
    return{
      value:'abc'
    }
  },
  methods:{
    handleClick:function(){
      this.$emit('myClick')
    },
  },
  template:`
  <div v-on:click='handleClick'>
    <slot :value='value' age="18" ></slot>
  </div>`
}


new Vue({
  components:{
    levelOne
  },
  data:function(){
    return{
      value:123
    }
  },
  methods:{
    handleClick:function(){
      alert(1)
    },
    handleClick2:function(){
      alert(2)
    }
  },
  template:`
  <div>
    <level-one v-on:myClick="handleClick2">
      <div slot-scope="props111">{{value}} {{props111.value}} {{props111.age}}</div>
    </level-one>
    <div v-on:click="handleClick">1</div>
  </div>`,

}).$mount('#app')

将template转化成render,

有一个nativeOn属性,作用是给组件添加原生事件

import Vue from 'vue/dist/vue.esm'

const levelOne={
  name: 'comp',
  data:function(){
    return{
      value:'abc'
    }
  },
  methods:{
    handleClick:function(){
     
      this.$emit('myClick')
   
    },
  },
  // template:`
  // <div v-on:click='handleClick'>
  //   <slot></slot>
  // </div>`,
  render(createElement) {
    return createElement('div',
    {
      on:{
        click:this.handleClick
      }
    },this.$slots.default)
  }
}


new Vue({
  components:{
    levelOne
  },
  data:function(){
    return{
      value:123
    }
  },
  methods:{
    handleClick2:function(){
      alert(2)
    }
  },
  // template:`
  // <div>
  //   <level-one v-on:myClick="handleClick2">
  //     <div>{{value}}</div>
  //   </level-one>
  // </div>`,
  render(createElement){
    return createElement(
      'level-one',
      {
       on:{
          myClick:this.handleClick2
        }
      },
     this.value
    )
    
  }

}).$mount('#app')

4.自定义组件的v-modle

首先了解v-modle做了什么事情

v-modle将变量和元素的props属性上value绑定在一起,当元素的input事件触发时,执行一个函数,这个函数是内部已经定义好的,接受一个参数,将这个参数赋值给v-model绑定的变量

new Vue({
  data:function(){
    return{
      value:123,
      value2:456
    }
  },
  methods:{
    handleInput:function(e){
      this.value=e.target.value
    }
  },
  template:`
  <div>
    <input type="text" @input="handleInput" :value="value">
    <div>{{value}}</div>
    <input type="text" v-model="value2">
    <div>{{value2}}</div>
  </div>`
}).$mount('#app')

也就是说给一个组件加上v-model时,将变量和组件props属性value的值绑定在一起,当组件触发input事件时,将一个值传递给事件函数的参数,就可以实现双向绑定。

import Vue from 'vue/dist/vue.esm'

Vue.config.productionTip = false;
const myComponent = {
  props:['value'],
  methods:{
    handleInput:function(e){
      this.$emit('input',e.target.value)
    }
  },
  template:`
  <div>
    <input type="text" @input="handleInput" :value="value">
  </div>`
}
new Vue({
  
  components:{
    myComponent
  },
  data:function(){
    return{
      number:123,
    }
  },
  template:`
  <div>
    <my-component v-model='number' />
    <div>{{number}}</div>
  </div>`
}).$mount('#app')

v-model默认和组件的input事件和props属性上的value相关,但是可以通过组件的modle属性进行修改

import Vue from 'vue/dist/vue.esm'

Vue.config.productionTip = false;
const myComponent = {
  model:{
    prop:'num',
    event:'myInput'
  },
  props:['num'],
  methods:{
    handleInput:function(e){
      this.$emit('myInput',e.target.value)
    }
  },
  template:`
  <div>
    <input type="text" @input="handleInput" :value="num">
  </div>`
}
new Vue({
  
  components:{
    myComponent
  },
  data:function(){
    return{
      number:123,
    }
  },
  template:`
  <div>
    <my-component v-model='number' />
    <div>{{number}}</div>
  </div>`
}).$mount('#app')

5.组件的继承

import Vue from 'vue/dist/vue.esm'

Vue.config.productionTip = false;
const myComponent = {
  props:{
    age:{
      required:true
    }
  },
  data(){
    return {
      num:123
    }
  },
  mounted(){
    console.log('myComponent')
  },
  template:`
  <div>
    <input type="text" :value="num">
    <div>{{name}}</div>
    <div>{{age}}</div>
  </div>`
}

const vueCom = Vue.extend(myComponent)
new vueCom({
  propsData:{
    age:18
  },
  mounted(){
    console.log('vueCom')
  },
  data:function(){
    return{
      num:456,
      name:"Jack"
    }
  },
}).$mount('#app')

网页页面显示内容:456  Jack  18,

控制台打印结果:myComponent,vueCom

说明data可以覆盖原先有的属性,生命周期不会。

6.组件实例的$parent属性,如果B组件在A组件中使用

const myComponent = {
  mounted(){
    console.log(this.$parent.$options.name)//Root
  },
  template:`<div>This is myComponent </div>`
}

new Vue({
  name:"Root",
  components:{
    myComponent
  },
  template:`<div><my-component/> </div>`
}).$mount('#app')

修改组件的parent,只有new的方式可以

不是通过new的方式定义parent,就不能生效。

const parentComponent = {
  name:parent
}
const myComponent = {
  parent:parentComponent,
  mounted(){
    console.log(this.$parent.$options.name)//Root
  },
  template:`<div>This is myComponent </div>`
}

new Vue({
  name:"Root",
  components:{
    myComponent
  },
  template:`<div><my-component/> </div>`
}).$mount('#app')

通过new的方式

import Vue from 'vue/dist/vue.esm'

//parentComponent组件必须要用new的方式
const parentComponent  = new Vue({
  name:'parent',
  template:`<div>This is parentComponent </div>`
}) 
const myComponent = {
  parent:parentComponent,
  mounted(){
    console.log(this.$parent.$options.name)//Root
  },
  template:`<div>This is myComponent </div>`
}
new Vue({
  parent:parentComponent,
  components: {
    myComponent
  },
  name:"Root",
  mounted(){
    console.log(this.$parent.$options.name)//parent
  },
  template:`<div><my-component/> </div>`
}).$mount('#app')

猜你喜欢

转载自blog.csdn.net/Night_Emperor/article/details/82997837
今日推荐