乐趣区

关于前端:我说这是全网最全vue组件通信方式你没意见吧

父子组件通信

prop
event
style 和 class
natvie 修饰符
$listeners
v-model
sync 修饰符
$parent 和 $children
$slots 和 $scopedSlots
ref    

跨组件通信

Provide 和 Inject
router
vuex
store 模式
eventbus

父子组件通信

prop

最常见的组件通信形式,由父组件向子组件传递。prop 可接管一个数组或对象

// 子组件
<script>
export default {
  name: "Comp",
  // 数组形式 props:[....]
  // ↓ 对象形式
  props: {
    datas: {
      type: Object,
      default: () => {return {};
      }
     },
  }
</script>

event

子组件向父组件发送告诉,并传递参数

子组件

methods:{
    // 通过 $emit 向父组件发送一个告诉
    handleEvent(){this.$emit('eventMsg', option)
    }
  }

父组件

methods:{
    // 监听子组件定义的办法
    eventMsg(option){console.log(option);
    }
  }

style 和 class

父组件能够向子组件传递 style 和 class,style 和 class 将合并到子组件根元素上

父组件


<template>
  <div id="app">
    <HelloWorld
      style="color:red"
      class="hello"
      msg="Welcome to Your Vue.js App"
    />
  </div>
</template>
​
<script>
import HelloWorld from "./components/HelloWorld.vue";
export default {
  components: {HelloWorld,},
};
</script>

子组件​


<template>
  <div class="world" style="text-align:center">
    <h1>{{msg}}</h1>
  </div>
</template>
​
<script>
export default {
  name: "HelloWorld",
  props: {msg: String,},
};
</script>

最终渲染后果


<div id="app">
  <div class="hello world" style="color:red; text-aling:center">
    <h1>Welcome to Your Vue.js App</h1>
  </div>
</div>

attribute

父组件在应用子组件时,在子组件上定义一些属性,这些属性将作用于子组件的根元素上,然而不包含 style 和 class

父组件


 
<HelloWorld data-a="1" data-b="2" msg="Welcome to Your Vue.js App" />
 

子组件


<template>
 <div>
   <h1>{{msg}}</h1>
 </div>
</template>
​
<script>
export default {
 name: "HelloWorld",
 props: {msg: String,},
 created() {
   // 通过 $attrs 获取父组件定义的 attribute
   console.log(this.$attrs); // {"data-a":"1","data-b":"2"}
 },
};
</script>

最终渲染后果


<div id="app">
  <div data-a="1" data-b="2">
    <h1>Welcome to Your Vue.js App</h1>
  </div>
</div>

Tip:子组件能够通过定义 inheritAttrs:false 来缓和 attribute 附着在子组件根元素上 但不影响通过 $attrs 获取数据

natvie 修饰符

在注册事件时,父组件能够通过 navite 修饰符,将事件注册到子组件根元素上

父组件


 
<template>
  <div id="app">
    <HelloWorld @click.native="handleClick" />
  </div>
</template>
​
<script>
import HelloWorld from "./components/HelloWorld.vue";
​
export default {
  components: {HelloWorld,},
  methods: {handleClick() {console.log(1);
    },
  },
};
</script>
 

子组件


 
<template>
  <div>
    <h1>Hello World</h1>
  </div>
</template>
 

最终渲染后果


<template>
 <div id="app">
   <h1>Hello World</h1>
 </div>
</template>
// 当点击 app 时。会触发父组件定义的 handleClick 办法

$listeners

子组件能够通过 $listeners 获取父组件传递过去的所有处理函数

v-model

父组件在应用子组件时,能够在子组件上绑定 v -model,子组件通过定义 model 的 prop 和 event 还获取父组件定义的值

父组件​
`

<Compn v-model=”datas” />
`
子组件


 
<script>
export default {
  // 分类筛选组件
  name: "sortFilter",
  // 定义实现 v -modal 的属性与事件
  model: {
    prop: "value",
    event: "change"
  },
  props: {
    // 绑定的值
    value: {type: [String, Number],
      default: ""
    }
   },
   created() {console.log(this.value)
  },
    
</script>
 

sync 修饰符

和 v-model 相似,用于双向数据绑定,不同点在于 v-model 只能针对一个数据进行绑定,而 sync 修饰符没有限度

子组件​

<template>
  <div>
    <p>
      <button @click="$emit(`update:num1`, num1 - 1)">-</button>
      {{num1}}
      <button @click="$emit(`update:num1`, num1 + 1)">+</button>
    </p>
    <p>
      <button @click="$emit(`update:num2`, num2 - 1)">-</button>
      {{num2}}
      <button @click="$emit(`update:num2`, num2 + 1)">+</button>
    </p>
  </div>
</template>
<script>
export default {props: ["num1", "num2"],
};
</script>
 

父组件​


<template>
 <div id="app">
   <Numbers :num1.sync="n1" :num2.sync="n2" />
   <!-- 等同于 -->
   <Numbers
     :num1="n1"
     @update:num1="n1 = $event"
     :num2="n2"
     @update:num2="n2 = $event"
   />
 </div>
</template>
<script>
import Numbers from "./components/Numbers.vue";
export default {
 components: {Numbers,},
 data() {
   return {
     n1: 0,
     n2: 0,
   };
 },
};
</script>

$parent 和 $children

在组件外部,能够通过 $parent 和 $children 属性,别离获取以后组件的父组件和子组件实例


<template>
 <div class="hello">
   <button @click="handelParent"> 获取父组件实例 </button>
   <button @click="handelChild"> 获取子组件实例 </button>
   <Child />
 </div>
</template>
​
<script>
import Child from "./Children.vue";
export default {
 name: "HelloWorld",
 props: {msg: String,},
 components: {Child,},
 methods: {handelParent() {console.log("父组件实例:", this.$parent);
   },
   handelChild() {console.log("子组件实例", this.$children);
   },
 },
};
</script>

ref

在应用组件时,能够通过在组件上定义 ref 来获取组件实例


 
<template>
  <div class="hello">
    <button @click="handelChild"> 获取子组件实例 </button>
    <Child ref="child" />
  </div>
</template>
<script>
import Child from "./Children.vue";
export default {
  name: "HelloWorld",
  props: {msg: String,},
  components: {Child,},
  methods: {handelChild() {console.log("子组件实例", this.$refs.child);
    },
  },
};
</script>
 

跨组件通信

provide 和 Inject

provide 和 inject 能够实现深层组件通信,顶层组件只需定义 provide,底层组件通过 inject 承受数据

顶层组件


// 父组件
provide(){msg:'hello Children'},
​
// 子组件
inject: ['msg']
created () {console.log(this.msg) // hello Children
}

router

如果一个组将扭转了地址栏,所有监听地址栏的组将都会做出相应的扭转,


// 监听路由变动
watch:{$route(to,from) {console.log(to,from);
   }
}

vuex

vuex 过于轻便,通常不倡议在小型我的项目中应用,小型我的项目能够应用 store 或 eventbus 代替 vuex,vuex 实质上就是一个数据仓库。在此不做过多赘述,先挖一个坑,下回再叙。

store 模式

store 模式其实就是一个一般的 js 模块,各组件能够导入该模块,将数据放到 data 外面,此时 store 就具备响应式了。

// 导出一个 store.js 模块
export default {userInfo:{...},
    loginInfo:{...}
}

// A 子组件导入 store 模块
import store from './store.js'
export default {
  name:'Acompon',
  data(){userInfo: store.userInfo}
}

// B 子组件导入 store 模块
import store from './store.js'
export default {
  name:'Bcompon',
  data(){loginInfo: store.loginInfo}
}
 

tip: store 模式的毛病是无奈跟踪数据的扭转,因为所有组件都能够更改数据

eventbus

eventbus 事件总线相当于一个桥梁,作为所有组将的一个事件核心,所有组件皆可往 eventbus 外面注册事件,也能够监听事件。


// 定义一个 eventbus 模块
import Vue from 'vue'
export const EventBus = new Vue()


// 在 main.js 里导入该模块并挂载到全局

// main.js
import eventbus from './eventbus.js'
Vue.prototype.$eventBus = eventbus


所有子组件向 eventbus 里组 注册 或者 监听 事件


 
// 组件 A 通过 $emit() 注册事件
sendMsg() {this.$eventBus.$emit("aMsg", 'from A');
}

// 组件 B 通过 $on 监听事件
this.$eventBus.$on("aMsg", (msg) => {
    // A 发送来的音讯
    console.log(msg) // from A
})

// 通过 $off() 能够敞开事件
退出移动版