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 方法。
触发方式:
  bus.$emit('time-start',value);,
注意:使用避免多个组件监听 同名的方法。bus适合碰到组件跨级兄弟组件等无明显依赖关系的消息传递,原生app开发中经常用到,
但是缺点是bus破坏了代码的链式调用,大量的滥用将导致逻辑的分散,出现问题后很难定位,降低了代码可读性。
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) 触发事件

 

 

 

 

 

  

posted @ 2020-01-13 19:13  石shi  阅读(101)  评论(0编辑  收藏  举报