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')

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章