1. 程式人生 > >Vue元件與元件間通訊

Vue元件與元件間通訊

元件的用法

註冊之後才能使用,註冊分區域性註冊和全域性註冊
元件和Vue例項類似,基本可以使用其所有內容(data,computed,methods,filters,watch)
與Vue例項不同,data是函式,輸入需要return

全域性註冊

<!DOCTYPE html>
<html>

<head>
  <title>show</title>
  <meta charset="utf-8">
</head>

<body>
  <div id="app">
<my-component></my-component> </div> <script src="https://cdn.bootcss.com/vue/2.5.13/vue.min.js"></script> <script> Vue.component('component', { template: `<div>Hello World</div>` }) new Vue({ el: '#app' }) </script> </body>
</html>

區域性註冊

<!DOCTYPE html>
<html>

<head>
  <title>show</title>
  <meta charset="utf-8">
</head>

<body>
  <div id="app">
    <my-component></my-component>
  </div>
  <script src="https://cdn.bootcss.com/vue/2.5.13/vue.min.js"
>
</script> <script> var component = { template: `<div>Hello World</div>` } new Vue({ el: '#app', components: { 'my-component' : component } }) </script> </body> </html>

使用props傳遞資料

元件不僅僅是要把模板的內容進行復用,更主要的是元件間要進行通訊。通常父元件的模板中包含子元件,父元件要正向的向子元件傳遞資料或引數,子元件接收到後根據引數的不同來渲染不同的內容或執行操作。這個正向傳遞資料的過程,就是通過props來實現的。

單向資料流

<!DOCTYPE html>
<html>

<head>
  <title>show</title>
  <meta charset="utf-8">
</head>

<body>
  <div id="app">
    <my-component :name="auctor" :test="888"></my-component>
  </div>
  <script src="https://cdn.bootcss.com/vue/2.5.13/vue.js"></script>
  <script>
  var component = {
    template: `<div>Hello World  {{msg}} {{showNum}}  {{showNum2}}</div>`,
    props: {
      name: String,
      testNumber: {
        type: Number,
        default: 666
      },
      test: {
        type: Number,
        validator: function(val) { // 自定義驗證函式
          return val < 10
        }
      }
    },
    data() {
      return {
        msg: this.name,
        showNum: this.testNumber,
        showNum2: this.test
      }
    }
  }

  new Vue({
    el: '#app',
    components: {
      'my-component': component
    },
    data() {
      return {
        auctor: 'Chengyu.Wang'
      }
    }
  })
  </script>
</body>

</html>

其中 props中的內容是有資料型別驗證的
1. String
2. Number
3. Boolean
4. Object
5. Array
6. Function
7. Symbol

// props 的具體寫法

props: { 
    dataA: String,   // 只能為字串
    dataB: [String,Number],   // 能為字串與數字
    dataC: {
        type: Boolean,   // 型別
        default: true    // 預設值
    },
    dataD: { 
        type: Number,
        required: true    // 是否為必傳
    },
    dataE: {
        type: Array,      // 如果資料是陣列或者物件,預設值必須是一個函式來返回
        default: function () {
            return []
        }
    },
    dataF: {
        validator: function(val){     // 自定義驗證函式
            return val > 10
        }
    }
}

元件間的通訊

父子間的元件通訊

子元件使用 $emit(eventName,data) 觸發事件

父元件使用 v-on:=’methodName’ 來監聽事件冒泡,從而獲取子元件的上傳的資料

<!DOCTYPE html>
<html>

<head>
  <title>show</title>
  <meta charset="utf-8">
</head>

<body>
  <div id="app">
    <my-component :name="auctor" v-on:reserve='handleReserveName'></my-component>
  </div>
  <script src="https://cdn.bootcss.com/vue/2.5.13/vue.js"></script>
  <script>
  var component = {
    template: `<div @click="reverseString">Hello World  {{msg}} </div>`,
    props: {
      name: String
    },
    data() {
      return {
        msg: this.name
      }
    },
    methods: {
      reverseString: function() {
        this.msg = this.msg.split('').reverse().join('')
        this.$emit('reserve', this.msg)
      }
    }
  }

  new Vue({
    el: '#app',
    components: {
      'my-component': component
    },
    data() {
      return {
        auctor: 'Chengyu.Wang'
      }
    },
    methods: {
      handleReserveName: function(val) {
        console.log(val)
        window.alert(val)
      }
    }
  })
  </script>
</body>

</html>

父子元件雙向繫結

使用 watch 來對監聽props,從而對屬性重新賦值

<!DOCTYPE html>
<html>

<head>
  <title>show</title>
  <meta charset="utf-8">
</head>

<body>
  <div id="app">
    This is Father num: {{num}}
    <button @click="handleFatherAdd">father add</button>
    <my-component :num="num" v-on:add='handleAdd'></my-component>
  </div>
  <script src="https://cdn.bootcss.com/vue/2.5.13/vue.js"></script>
  <script>
  var component = {
    template: `<div>This is child Num: {{shu}} <button @click="handleAdd">child add</button></div>`,
    props: {
      num: Number
    },
    data() {
      return {
        shu: this.num
      }
    },
    // watch 部分是核心程式碼,可以註釋試試效果
    watch: {
      num: function(val) {
        this.shu = val
      }
    },
    methods: {
      handleAdd: function() {
        this.shu++
          this.$emit('add', this.shu)
      }
    }
  }

  new Vue({
    el: '#app',
    components: {
      'my-component': component
    },
    data() {
      return {
        num: 666
      }
    },
    methods: {
      handleAdd: function(val) {
        this.num = val
      },
      handleFatherAdd: function() {
        this.num++
      }
    }
  })
  </script>
</body>

</html>

非父子元件之間的通訊

非父子關係的兩個元件之間也需要通訊。在簡單的場景下,可以使用一個空的 Vue 例項作為事件匯流排:

<!DOCTYPE html>
<html>

<head>
  <title>show</title>
  <meta charset="utf-8">
</head>

<body>
  <div id="app">
    {{msg}}
    <my-component></my-component>
  </div>
  <script src="https://cdn.bootcss.com/vue/2.5.13/vue.js"></script>
  <script>
  var middle = new Vue()
  var component = {
    template: `<button @click="handle">點我</button>`,
    methods: {
      handle: function() {
        middle.$emit('handleAAA', Math.random().toString(35).substr(2, 50))
      }
    }
  }

  new Vue({
    el: '#app',
    components: {
      'my-component': component
    },
    data() {
      return {
        msg: 'AAA'
      }
    },
    mounted() {
      var _this = this
      middle.$on('handleAAA', function(val) {
        _this.msg = val
      })
    }
  })
  </script>
</body>

</html>

元件的高階用法

遞迴元件

<!DOCTYPE html>
<html>

<head>
  <title>show</title>
  <meta charset="utf-8">
</head>

<body>
  <div id="app">
    <my-component :count="5"></my-component>
  </div>
  <script src="https://cdn.bootcss.com/vue/2.5.13/vue.js"></script>
  <script>
  var middle = new Vue()
  var component = {
    template: `<div><my-component :count='count-1' v-if="count > 0"></my-component>{{count}}</div>`,
    props: {
      count: Number
    },
    name: 'myComponent' // 核心程式碼
  }

  new Vue({
    el: '#app',
    components: {
      'my-component': component
    },
    data() {
      return {}
    }
  })
  </script>
</body>

</html>