Vue-組件

1、組件的兩種使用方法html

2、使用props傳遞數據vue

3、單向數據流git

4、組件中的命名方式github

5、數據驗證數組

6、組件通訊app

7、slot(插槽)函數

8、動態組件ui

 

Vue中的組件

  • 組件是可複用的Vue實例
  • 命名組件推薦使用小寫字母,用-鏈接
  • 在組件定義中,除了template,其它選項還有:data,methods,computed
  • 組件定義中的data必須是一個方法

 

1、組件的兩種使用方法

全局註冊

<my-component></my-component>
Vue.component('my-component',{
   template: '<div>組件內容</div>'
})

 

局部註冊

var app = new Vue({
   el:'#app',
   components:{
       ''my-components:{
            template:'<div>組件內容</div>'
        }
     }  
})

 

2、使用props傳遞數據

這邊的props採用數組方式this

父組件向子組件傳遞數據spa

v-bin動態綁定父組件傳的內容

<div id="app" style="width:300px;height:200px;border:2px solid skyblue">
  <child-component msg="我是父組件的內容"></child-component>
  <hr>
 <!--  v-bind進行動態數據動態綁定 將input中的sth傳給子組件 -->
  <input type="text" v-model="dadmsg">
  <bind-component :sth="dadmsg"></bind-component>
</div>
var app = new Vue({
  el: '#app',
  data: {
    dadmsg: 'happy'
  },
  components: {
    'child-component': {
      props: ['msg'],
      template: '<div>{{msg}}</div>'
    },
    'bind-component': {
      props: ['sth'],
      template: '<div>{{sth}}</div>'
    }
  }
})

在組件中使用props來從父組件接收參數,在props中的屬性,均可以在組件中直接使用。

 

3、單向數據流

概念理解:經過props傳遞數據是單向的,父組件變化時數據會傳給子組件,可是反過來不行。

目的:是將父子組件解稿,避免子組件修改無心間修改了父組件的狀態。

兩種改變prop的狀況的應用場景

  • 父組件傳遞初始值,子組件能夠將它做爲初始值保存起來,在本身的做用域下能夠隨意進行修改;
  • 將傳遞進來的數據做爲初始值進行保存
  1. 註冊組件
  2. 將父組件的數據傳遞進來,並在子組件中props接收
  3. 將傳遞進來的數據經過初始值保存起來
<div id='app'>
  <child-component msg='今天也要努力啊'></child-component>
</div>
let app = new Vue({
  el: '#app',
  components: {
    'child-component': {
      props: ['msg'],
      template: '<div>{{count}}</div>',
      data() {
        return {
          count: this.msg
        }
      }
    }
  }
})

 

prop做爲須要被轉變的原始值傳入,用計算屬性對其再次進行計算

  1. 註冊組件
  2. 將父組件的數據傳遞進來,並在子組件中使用props接收
  3. 將傳遞進來的數據經過計算屬性進行從新計算並渲染到頁面
<div id="app">
  <input type="text" v-model="width">
  <width-component :width='width'></width-component>
</div>
let app = new Vue({
  el: "#app",
  data: {
    width: 0
  },
  components: {
    'width-component': {
      props: ['width'],
      template: '<div :style="style"></div>',
      computed: {
        style() {
          return {
            width: this.width + 'px',
            background: 'red',
            height: '30px'
          }
        }
      }
    }
  }
})

 

4、組件中的命名方式

camelCased (駝峯式)

kebab­case(短橫線命名)

  • 組件中的html中、父組件給子組件傳遞數據,必須使用短橫線命名。  (a-bc √    aBc ×)
  • 在props中,短橫線命名駝峯命名均可以。
  • 在template中,必須使用駝峯命名,短橫線會報錯。
  • 在data中,使用this.xxx時,必須使用駝峯命名,短橫線會報錯。
  • 組件的命名,短橫線命名駝峯命名均可以。

 

5、數據驗證

這邊的props採用對象方式

可驗證的類型:Number  String  Boolean  Array  Object  Function  自定義

<div id="app">
  <style-component :a='a' :b='b' :c='c' :d='d' :e='e' :g='g'></style-component>
</div>
let app = new Vue({
  el: '#app',
  data: {
    a: 1,
    b: '2',
    c: '', //空字符串,就取默認的true
    d: [111, 222, 333],
    e: console.log(),
    g: 3
  },
  components: {
    'styleComponent': {
      props: {
        //數字類型
        a: {
          type: Number,
          required: true //必傳
        },
        //字符串類型
        b: {
          type: [String, Number]
        },
        //布爾類型
        c: {
          type: Boolean,
          default: true //默認值
        },
        //數組或對象  默認值是函數形式返回
        d: {
          type: Array,
          default: function() {
            return []
          }
        },
        //函數類型
        e: {
          type: Function
        },
        //自定義一個函數
        g: {
          validator: function(value) {
            return value < 10
          }
        }

      },
      template: '<div>{{a}}--{{b}}--{{c}}--{{d}}--{{g}}</div>'
    }
  }
})

 

六 、組件通訊

子組件向父組件傳遞數據

——給父組件添加自定義事件

——子組件經過$emit觸發事件

  1. 給父組件添加自定義事件
  2. 子組件$emit傳出數據
  3. 自定義事件函數接收數據參數並賦值,渲染
<div id="app">
  <p>您的帳戶餘額爲{{num}}</p>
  <btn-component @change='change'></btn-component>
</div>
new Vue({
  el: '#app',
  data: {
    num: 3000
  },
  methods: {
    change(value) {
      this.num = value
    }
  },
  components: {
    'btn-component': {
      template: '<div>\
                    <button @click="hangle_ad">+1000</button> \
                    <button @click="hangle_re">-1000</button> \
                </div>',
      data() {
        return {
          count: 3000
        }
      },
      methods: {
        hangle_ad() {
          this.count += 1000
          this.$emit('change', this.count)
        },
        hangle_re() {
          this.count -= 1000
          this.$emit('change', this.count)
        }
      }
    }
  }
})

 

——v-model代替自定義事件

v-model實質背後作了兩個操做

  1. v-bind綁定一個value屬性  (父組件要接收一個value值)
  2. v-on指令給當前元素綁定input事件  (子組件在有新的value值得時候要觸發一個input事件)

因此上面那個銀行存款的demo能夠改成

<div id="app">
  <p>您的帳戶餘額爲{{num}}</p>
  <btn-component v-model='num'></btn-component>  這邊改啦!!
</div>
new Vue({
  el: '#app',
  data: {
    num: 3000
  },                               //父組件沒有自定義函數啦!!
  components: {
    'btn-component': {
      template: '<div>\
                    <button @click="hangle_ad">+1000</button> \
                    <button @click="hangle_re">-1000</button> \
                </div>',
      data() {
        return {
          count: 3000
        }
      },
      methods: {
        hangle_ad() {
          this.count += 1000
          this.$emit('input', this.count)  //這邊改啦!!
        },
        hangle_re() {
          this.count -= 1000
          this.$emit('input', this.count)   //這邊改啦!!
        }
      }
    }
  }
})        

 

非父組件之間的通訊

兩個非父子關係的組件進行通訊,可使用一個空的Vue實例做爲中央事件總線(中介)

<div id="app">
  <ahandle></ahandle>
  <bhandle></bhandle>
</div>
var app = new Vue({
  el: '#app',
  data: {
    bus: new Vue() //bus中介
  },
  components: {
    'ahandle': {
      template: '<div><button @click="aclick">點擊向b組件傳遞數據</button></div>',
      data() {
        return {
          aaa: '我是來自a組件的內容'
        }
      },
      methods: {
        aclick() { //a組件建立事件,供b組件監聽   由bus中介$emit提交
          this.$root.bus.$emit('givetob', this.aaa)
        }
      }
    },
    'bhandle': {
      template: '<div>我是b組件</div>',
      created() { //b組件監聽a組件建立的事件   由bus中介$on監聽
        this.$root.bus.$on('givetob', function(value) { //這裏的value就是a組件傳進來的this.aaa
          alert(value)
        })
      }
    }
  }
})

 

父鏈  $.parent

<div id="app">
<btn-component></btn-component>--{{msg}}
</div>
let app = new Vue({
  el: '#app',
  data: {
    msg: '我是父組件,我如今沒有內容'
  },
  components: {
    'btn-component': {
      template: '<button @click="changeFather">點擊修改父組件中的內容</button>',
      methods: {
        changeFather() {
          this.$parent.msg = '我如今有內容啦'
        }
      }
    }
  }
})

 

子鏈 $children

vue提供索引:$ref

<div id="app">
  <button @click='getchild'>點擊父組件按鈕獲取a組件內容</button>
  <a-component ref='a'></a-component>   添加索引ref
  <b-component ref='b'></b-component>
  {{msg}}
</div>
let app = new Vue({
  el: '#app',
  data: {
    msg: '子組件數據未得到'
  },
  methods: {
    getchild() {
      this.msg = this.$refs.a.msg  //獲取a組件的內容 ---refs
    }
  },
  components: {
    'a-component': {
      template: '<span></span>',
      data() {
        return {
          msg: '我是a組件中的內容'
        }
      }
    },
    'b-component': {
      template: '<span></span>',
      data() {
        return {
          msg: '我是b組件中的內容'
        }
      }
    }
  }
})

 

7、slot(插槽)

使用slot進行分發內容

 

編譯的做用域

父組件模板的內容在父組件做用域中編譯;

子組件模板的內容在子組件做用域內編譯。

 

插槽的用法

混合父組件的內容與子組件本身的模板

  • 單個插槽
<div id="app">
  <slotcomponent>
    <p>父組件插入到子組件的內容——我把子組件的slot替換掉啦</p>
  </slotcomponent>
</div>
new Vue({
  el: '#app',
  components: {
    'slotcomponent': {
      template: '<slot>父組件沒有插入內容沒有內容就顯示這個</slot>'
    }
  }
})

 

  • 具名插槽
    <div id="app">
        <name-component>
            <h2 slot="header">標題</h2>
            <p>內容1</p>
            <p>內容2</p>
            <p slot="footer">底部</p>
        </name-component>
    </div>
 let app = new Vue({
            el: '#app',
            components: {
                'name-component': {
                    template: '<div> \
                        <div class="header"> \
                            <slot name="header"></slot> \
                        </div> \
                        <div class="container"> \
                            <slot></slot> \
                        </div> \
                        <div class="footer"> \
                            <slot name="footer"></slot> \
                        </div> \
                    </div>'
                }
            }
        })

 

  • 做用域插槽
<div id="app">
  <mycomponent>
    <p slot='aaa' slot-scope='child'>
      {{child.text}} name拿不到
    </p>
  </mycomponent>
</div>
let app = new Vue({
  el: '#app',
  components: {
    'mycomponent': {
      template: '<div>\
      <slot text="我是子組件插槽的內容" name="aaa"></slot>\
      </div>'
    }
  }
})

*2.5.0以前都是用template中寫,渲染的是template中的內容

<div id="app">
  <mycomponent>
    <template slot='aaa' slot-scope='child'>
      {{child.text}} name拿不到
    </template>
  </mycomponent>
</div>

 

訪問slot

this.$slot.插槽名稱

在具名插槽的例子前提下添加代碼

......
components:{
......
mounted(){
     var header = this.$slots.header
     console.log(header) //此處拿到的是虛擬節點
     var headerin = this.$slots.header[0].elm.innerText
     console.log(headerin)
     }
}

 

8、動態組件

使用Vue提供的component元素,動態掛載不一樣的組件

使用is特性來實現

代碼

 

待補充待補充待補充......

相關文章
相關標籤/搜索