vuejs 小技巧二 组件模块化时 各种传值骚操作
一:路由跳转,这就不多说了,简单一个小列子:
跳转:
接受:
二:通过$parent,$chlidren等方法调取用层级关系的组件内的数据和方法(不建议使用,灵活性太差,没法体现公共组件的随意调用)
这个简单不多做介绍,也没啥用,真正的模块化使用这种方法局限性太大了
三:bus 总线
1: 先定义一个bus.,js 文件,内容如下:
使用方法:
创建事件监听的vue 文件:
<template> <div class="q-timer"> {{ time | fmtClock }} </div> </template> <script> //. 引入bus import bus from '@/js/bus' export default{ data() { return { time: 0, id: null } }, methods: { startTimer(time) { this.time = time this.id = setInterval(() => { if (this.time <= 0) { bus.$emit('time-end') clearInterval(this.id) return } this.time-- }, 1000) }, }, mounted() { //bus 事件监听 方法 bus.$on('time-start', time => { // 匿名函数里调用 方法 this.startTimer(time) }) bus.$on('time-clear', () => { clearInterval(this.id) }) }, beforeDestroy() { // 组件销毁时 bus 事件销毁 bus.$off('time-start') bus.$off('time-clear') }, } </script>
bus
适合碰到组件跨级兄弟组件等无明显依赖关系的消息传递,原生app开发中经常用到,bus
破坏了代码的链式调用,大量的滥用将导致逻辑的分散,出现问题后很难定位,降低了代码可读性。
四: vue 新增的 $attrs 与 $listeners
4.1: 适用于 a 组件 包含 b 组件,b组件包含 c 组件 ,然后 c 组件可以触发 a 组件或者b组件的函数。也可以说是: 现在我么需要在A中对C的props赋值,监听C的emit事件。
$attrs--继承所有的父组件属性(除了prop传递的属性、class 和 style ),一般用在子组件的子元素上
$listeners--属性,它是一个对象,里面包含了作用在这个组件上的所有监听器,你就可以配合 v-on="$listeners"
将所有的事件监听器指向这个组件的某个特定的子元素。(相当于子组件继承父组件的事件)
在vue2.4中,为了解决该需求,引入了$attrs
和$listeners
,新增了inheritAttrs
选项。我们只需要在B组件中对引入的C组件增加下面两个属性即可绑定所有的属性和事件。
<C v-bind="$attrs" v-on="$listeners"></C>
a 组件:
<template> <div> <h2>组件A 数据项:{{myData}}</h2> <B @changeMyData="changeMyData" :myData="myData"></B> </div> </template> <script> import B from "./B"; export default { data() { return { myData: "100" }; }, components: { B }, methods: { changeMyData(val) { this.myData = val; } } }; </script>
b 组件:
<template> <div> <h3>组件B</h3> <C v-bind="$attrs" v-on="$listeners"></C> </div> </template> <script> import C from "./C"; export default { components: { C }, };
c组件:
<template> <div> <h5>组件C</h5> <input v-model="myc" @input="hInput" /> </div> </template> <script> export default { props: { myData: { String } }, created() { this.myc = this.myData; // 在组件A中传递过来的属性 console.info(this.$attrs, this.$listeners); }, methods: { hInput() { this.$emit("changeMyData", this.myc); // // 在组件A中传递过来的事件 } } }; </script>
五:props 父子组件传值。
父组件 :<Parent :todos="todos"></Parent>
子组件中使用props来接受父组件传入的值
<template> <ul> <li v-for="item in todos">{{item}}</li> </ul> </template> <script> export default { name : "child", props : ["todos"], // todos需与父组件中:todos名称一致 } </script>
六: v-mode ,$emit(‘input’,value)
vue 再父子组件传值时,除了传统的父组件 :属性去传值外,还可以使用 父组件v-model传值,子组件props['value']接收,
而子组件也可以通过$emit('input',false),去改变父组件中v-model 和 子组件中 value 的值 。
@click="$emit('input',false)" 意思死 点击click 事件触发了 input 事件并传入false 值, 等价于 @click="clickEmit"
<!--父组件--> <template> <test v-model = "isShow"></test> <button @click="isShow = !isShow">switch</button> </template> <script> import test from '../test'; export default { components: { test }, data() { return { isShow: false } } } </script>
<!--子组件--> <template> <div> <div>{{value}}</div> <Button @click="$emit('input',false)">关闭</Button> </div> </template> <script type="text/ecmascript-6"> export default { props:['value'], mounted() { console.log(this.value) } } </script>
七: 使用$emit传值 , 这种方式,主要是借助于$emit触发组件内部的方法,然后将数据传递到组件方法中实现传值,在父组件中将一个方法绑定到子组件中,
然后通过点击子组件中的元素触发父组件中的事件完成传值。 子组件触发
this.$emit("letHaveTry","把想传的值放在这") 父组件 监听 @letHaveTry="lookMe" ,lookMe 就是父组件的 函数
父组件:
1 <template> 2 <Child @letHaveTry="lookMe"></Child> 3 </template> 4 <script> 5 export default { 6 name : "parent", 7 methods : { 8 lookMe : function(e){ 9 console.log("就这么传过来" + e) 10 } 11 } 12 } 13 14 </script>
子组件:
<template>
<button @click="haveTry">敢点击我我就敢甩锅。</button> </template> <script> export default { name : "child", methods : { haveTry : function(){ this.$emit("letHaveTry","把想传的值放在这") } } } </script>
八:我们或许会遇到过这种问题,比如 组件 a 与b 通过 this.$router 跳转到组件c , 组件a 与 组件 b 都需要 触发 组件 c中的 一个 方法时,由于组件c 是通过跳转 打开的新地址, 所以 组件c 中的方法 不好透露 到组件 a 与 组件b中,这时候 我们 就可以通过
this.$router 中的 params 与 eval 来传递 给组件c 中方法 具体的值,代码如下:
组件a 中跳转到 组件c 的函数
clickLookAnswer(val){
this.$router.replace({name:'answer',query:{examId:this.examId},params:{exec:"location.href='/'"}});
},
组件b 组件c 的函数
clickLookAnswer(val){
this.$router.replace({name:'answer',query:{examId:this.examId},params:{exec:` localStorage.setItem("page-name",'2');window.history.go(-1)`}});
},
组件c 中 触发 比如一个相同的事件 ,关闭考试的 函数
returnExam() {
var exec = this.$route.params.exec;
if(exec){
eval(exec);
}else{
window.history.go(-1);
}
},
九:vuex 组件传值(vue3.0 后由于使用proxy 实心了双向绑定,vuex 可以放弃使用了)
十:vue 的自定义事件
使用 $on(eventName) 监听事件
使用 $emit(eventName) 触发事件