vue的多种通信方式

方法1: Prop

<div id="app">
  <child :content="message"></child>
</div>

// Js
let Child = Vue.extend({
  template: '<h2>{{ content }}</h2>',
  props: {
    content: {
      type: String,
      default: () => { return 'from child' }
    }
  }
})

new Vue({
  el: '#app',
  data: {
    message: 'from parent'
  },
  components: {
    Child
  }
})

方法2: $emit

<div id="app">
  <my-button @greet="sayHi"></my-button>
</div>
let MyButton = Vue.extend({
  template: '<button @click="triggerClick">click</button>',
  data () {
    return {
      greeting: 'vue.js!'
    }
  },
  methods: {
    triggerClick () {
      this.$emit('greet', this.greeting)
    }
  }
})

new Vue({
  el: '#app',
  components: {
    MyButton
  },
  methods: {
    sayHi (val) {
      alert('Hi, ' + val) // 'Hi, vue.js!'
    }
  }
})
3. .sync 修饰符
<text-document
  v-bind:title="doc.title"
  v-on:update:title="doc.title = $event">
</text-document>
可以简写为:
<text-document v-bind:title.sync="doc.title"></text-document>
// ===============
<div id="app">
  <login :name.sync="userName"></login> {{ userName }}
</div>
let Login = Vue.extend({
  template: `
    <div class="input-group">
      <label>姓名:</label>
      <input v-model="text">
    </div>
  `,
  props: ['name'],
  data () {
    return {
      text: ''
    }
  },
  watch: {
    text (newVal) {
      this.$emit('update:name', newVal)
    }
  }
})

new Vue({
  el: '#app',
  data: {
    userName: ''
  },
  components: {
    Login
  }
})
4. $attrs & $listeners
// 组件A
Vue.component('A', {
  template: `
    <div>
      <p>this is parent component!</p>
      <B :messagec="messagec" :message="message" v-on:getCData="getCData" v-on:getChildData="getChildData(message)"></B>
    </div>
  `,
  data() {
    return {
      message: 'hello',
      messagec: 'hello c' //传递给c组件的数据
    }
  },
  methods: {
    // 执行B子组件触发的事件
    getChildData(val) {
      console.log(`这是来自B组件的数据:${val}`);
    },

    // 执行C子组件触发的事件
    getCData(val) {
      console.log(`这是来自C组件的数据:${val}`);
    }
  }
});

// 组件B
Vue.component('B', {
  template: `
    <div>
      <input type="text" v-model="mymessage" @input="passData(mymessage)">
      <!-- C组件中能直接触发 getCData 的原因在于:B组件调用 C组件时,使用 v-on 绑定了 $listeners 属性 -->
      <!-- 通过v-bind 绑定 $attrs 属性,C组件可以直接获取到 A组件中传递下来的 props(除了 B组件中 props声明的) -->
      <C v-bind="$attrs" v-on="$listeners"></C>
    </div>
  `,
  /**
   * 得到父组件传递过来的数据
   * 这里的定义最好是写成数据校验的形式,免得得到的数据是我们意料之外的
   *
   * props: {
   *   message: {
   *     type: String,
   *     default: ''
   *   }
   * }
   *
  */
  props: ['message'],
  data(){
    return {
      mymessage: this.message
    }
  },
  methods: {
    passData(val){
      //触发父组件中的事件
      this.$emit('getChildData', val)
    }
  }
});

// 组件C
Vue.component('C', {
  template: `
    <div>
      <input type="text" v-model="$attrs.messagec" @input="passCData($attrs.messagec)">
    </div>
  `,
  methods: {
    passCData(val) {
      // 触发父组件A中的事件
      this.$emit('getCData',val)
    }
  }
});

var app=new Vue({
  el:'#app',
  template: `
    <div>
      <A />
    </div>
  `
});

作者:LinFun
链接:https://juejin.im/post/5dc8bd4b6fb9a04a640d7131
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
5. provide & inject
<div id="app">
  <son></son>
</div>
let Son = Vue.extend({
  template: '<h2>son</h2>',
  inject: {
    house: {
      default: '没房'
    },
    car: {
      default: '没车'
    },
    money: {
      // 长大工作了虽然有点钱
      // 仅供生活费,需要向父母要
      default: '¥4500'
    }
  },
  created () {
    console.log(this.house, this.car, this.money)
    // -> '房子', '车子', '¥10000'
  }
})
new Vue({
  el: '#app',
  provide: {
    house: '房子',
    car: '车子',
    money: '¥10000'
  },
  components: {
    Son
  }
})
6 slot-scope & v-slot

请注意, v-slot 只能添加到 或自定义组件上,这点与弃用的 slot 属性不同

7 scopedSlots
8 EventBus
9 vuex
10 $parent $children
// 定义 parent 组件
Vue.component('parent', {
  template: `
    <div>
      <p>this is parent component!</p>
      <button @click="changeChildValue">test</button>
      <child />
    </div>
  `,
  data() {
    return {
      message: 'hello'
    }
  },
  methods: {
    changeChildValue(){
      this.$children[0].mymessage = 'hello';
    }
  },
});

// 定义 child 组件
Vue.component('child', {
  template:`
    <div>
      <input type="text" v-model="mymessage" @change="changeValue" />
    </div>
  `,
  data() {
    return {
      mymessage: this.$parent.message
    }
  },
  methods: {
    changeValue(){
      this.$parent.message = this.mymessage;//通过如此调用可以改变父组件的值
    }
  },
});

const app = new Vue({
  el: '#app',
  template: `
    <div>
      <parent />
    </div>
  `
});
11 $root
12 broadcast / dispatch
// broadcast 方法的主逻辑处理方法
function broadcast(componentName, eventName, params) {
  this.$children.forEach(child => {
    const name = child.$options.componentName;

    if (name === componentName) {
      child.$emit.apply(child, [eventName].concat(params));
    } else {
      broadcast.apply(child, [componentName, eventName].concat(params));
    }
  });
}

export default {
  methods: {
    // 定义 dispatch 方法
    dispatch(componentName, eventName, params) {
      let parent = this.$parent;
      let name = parent.$options.componentName;
      while (parent && (!name || name !== componentName)) {
        parent = parent.$parent;

        if (parent) {
          name = parent.$options.componentName;
        }
      }

      if (parent) {
        parent.$emit.apply(parent, [eventName].concat(params));
      }
    },

    // 定义 broadcast 方法
    broadcast(componentName, eventName, params) {
      broadcast.call(this, componentName, eventName, params);
    }
  }
};

####### 13 v-model

<custom-input
  v-bind:value="searchText"
  v-on:input="searchText = $event"
></custom-input>
// =====
// 子组件
Vue.component('custom-input', {
  props: ['value'],
  template: `
    <input
      v-bind:value="value"
      v-on:input="$emit('input', $event.target.value)"
    >
  `
})
父组件
<custom-input v-model="searchText"></custom-input>

####### 14 refs

// 父组件
<home ref="home"/>

mounted(){
  console.log(this.$refs.home) //即可拿到子组件的实例,就可以直接操作 data 和 methods
}
15 Vue.observable
// 文件路径 - /store/store.js
import Vue from 'vue'

export const store = Vue.observable({ count: 0 })
export const mutations = {
  setCount (count) {
    store.count = count
  }
}

//使用
<template>
    <div>
        <label for="bookNum">数 量</label>
            <button @click="setCount(count+1)">+</button>
            <span>{{count}}</span>
            <button @click="setCount(count-1)">-</button>
    </div>
</template>

<script>
import { store, mutations } from '../store/store' // Vue2.6新增API Observable

export default {
  name: 'Add',
  computed: {
    count () {
      return store.count
    }
  },
  methods: {
    setCount: mutations.setCount
  }
}
</script>
参考文档。

添加链接描述
添加链接描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值