vue所有组件传值方法的应用__Vue.js
发布于 4 年前 作者 banyungong 1942 次浏览 来自 分享
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利

前言:

最近做项目接触到了几乎所有vue的传值方法,在此做个记录,省的自己之后写的时候到处百度,还百度到的是错的!!!工作中让你配置路由,让你做个请求拦截啥的可能都是做好了的,用的并不多,但是vue的组件传值,以及如何调用父组件或者子组件的方法比常用的指令还要频繁,所以有必要做个记录!!!

props/$emit父子组件传值:

父传子:

  • 父组件:
  <template>
    <div id="app">
      <Home :msg="msg"></Home>
    </div>
  </template>

  <script lang="ts">
  import Vue from 'vue';
  import Home from '@/views/Home';

  export default Vue.extend({
    name: 'App',
    components: {
      Home
    },
    data(){
        return {
            msg:"我是父元素传过来的值"
        }
    }
  });
  </script>
  • 子组件
  <template>
    <div class="home">
      {{msg}}
    </div>
  </template>

  <script>
  export default {
    name: 'Home',
    components: {

    },
    props:{
        msg:String,
    }
  }

子传父:(是通过事件传值来进行具体实现的)

  • 子组件:
  <template>
    <div class="home">
      <button @click="toValue">点击</button>
    </div>
  </template>

  <script>
  export default {
    name: 'Home',
    components: {

    },
    methods:{
        toValue(){
            this.$emit("receive","我是子组件传过来的值");
        }
    }
  }
  </script>
  • 父组件:
  <template>
    <div id="app">
       <p>{{msg}}</p>
      <Home @receive="receive"></Home>
    </div>
  </template>

  <script lang="ts">
  import Vue from 'vue';
  import Home from '@/views/Home';

  export default Vue.extend({
    name: 'App',
    components: {
      Home
    },
    data(){
        return {
            msg:'',
        }
    },
    methods:{
        receive(val){
            this.msg = val;
        }
    }
  });
  </script>

ref与$ parent/$children父子组件传值:

父传子:

  • 父组件
  <template>
    <div id="app">
      <Home ref="home"></Home>
      <button @click="toValue">点击</button>
    </div>
  </template>

  <script lang="ts">
  import Vue from 'vue';
  import Home from '@/views/Home';

  export default Vue.extend({
    name: 'App',
    components: {
      Home
    },
    data(){
        return {
            msg:'',
        }
    },
    methods:{
       toValue(){
          this.msg = "这是父组件的值";
          this.$refs.home.setMsg(this.msg);
       }
    }
  });
  </script>
  • 子组件:
  <template>
    <div class="home">
      {{msg}}
    </div>
  </template>

  <script>
  export default {
    name: 'Home',
    components: {

    },
    data(){
        return {
            msg:''
        }
    },
    methods:{
        setMsg(val){
            this.msg = val;
        }
    }
  }
  </script>

子传父:

  • 子组件(如果子组件是公共组件,需判断父组件是否具有该方法)
  <template>
    <div class="home">
      <button @click="setMsg">点击</button>
    </div>
  </template>

  <script>
  export default {
    name: 'Home',
    components: {

    },
    data(){
        return {
            msg:'这是子组件的值'
        }
    },
    methods:{
        setMsg(){
            this.$parent.toValue(this.msg);
        }
    }
  }
  </script>
  • 父组件
  <template>
    <div id="app">
      {{msg}}
      <Home></Home>
    </div>
  </template>

  <script lang="ts">
  import Vue from 'vue';
  import Home from '@/views/Home';

  export default Vue.extend({
    name: 'App',
    components: {
      Home
    },
    data(){
        return {
            msg:'',
        }
    },
    methods:{
       toValue(val){
          this.msg = val;
       }
    }
  });
  </script>

$ attrs/$listeners隔代组件传值(爷孙组件参数互传)

爷传孙

  • 爷组件
  <template>
    <div id="app">
      <Home :msg="msg"></Home>
    </div>
  </template>

  <script lang="ts">
  import Vue from 'vue';
  import Home from '@/views/Home';

  export default Vue.extend({
    name: 'App',
    components: {
      Home
    },
    data(){
        return {
            msg:'这是爷组件的值'
        }
    }
  });
  </script>
  • 父组件(父组件的操作最简单,但不做就会传不过去)
  <template>
    <div class="home">
      <Sun v-bind="$attrs"></Sun>
    </div>
  </template>

  <script>
  import Sun from './component/Sun.vue'
  export default {
    name: 'Home',
    components: {
      Sun
    },
  }
  </script>
  • 孙组件
  <template>
    <div class="sun">
      {{msg}}
    </div>
  </template>

  <script>
  export default {
    name: 'Sun',
    props:{
        msg:String,
    }
  }
  </script>

孙传爷:

  • 孙组件
  <template>
    <div class="sun">
      <button @click="toVal">点我</button>
    </div>
  </template>

  <script>
  export default {
    name: 'Sun',
    data(){
        return {
            msg:"这是孙组件的值",
        }
    },
    methods:{
        toVal(){
            this.$emit("setVal",this.msg)
        }
    }
  }
  </script>
  • 父组件
  <template>
    <div class="home">
      <Sun v-on="$listeners"></Sun>
    </div>
  </template>

  <script>
  import Sun from './component/Sun.vue'
  export default {
    name: 'Home',
    components: {
      Sun
    },
  }
  </script>
  • 爷组件
  <template>
    <div id="app">
       <p>{{msg}}</p>
      <Home @setVal="setVal"></Home>
    </div>
  </template>

  <script lang="ts">
  import Vue from 'vue';
  import Home from '@/views/Home';

  export default Vue.extend({
    name: 'App',
    components: {
      Home
    },
    data(){
        return {
            msg:''
        }
    },
    methods:{
        setVal(val){
            this.msg = val;
        }
    }
  });
  </script>

provide/inject隔代组件传值(祖先组件传给其任意后代元素)

提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。如果传入的值是字符串,数字,布尔值等基本类型则会无响应!!!

爷传孙(所有后代组件都能拿到该值,但传动态值必须是个对象!!!)

  • 祖先组件(其实不用写那个事件就能完成传值)
  <template>
    <div id="app">
      <button @click="setVal">点击</button>
      <Home></Home>
    </div>
  </template>

  <script lang="ts">
  import Vue from 'vue';
  import Home from '@/views/Home';

  export default Vue.extend({
    name: 'App',
    components: {
      Home
    },
    provide(){
        return {
            data:this.dataObj
        }
    },
    data(){
        return {
            dataObj:{
                msg:'这是爷组件的值',
                num:1
            }
        }
    },
    methods:{
        setVal(){
            this.dataObj.num++;
        }
    }
  });
  </script>
  • 后代组件(任意一个后代元素通过该写法都能拿到值)
  <template>
    <div class="sun">
      <p>{{txt}}</p>
    </div>
  </template>

  <script>
  export default {
    name: 'Sun',
    inject:['data'],
	computed:{
		txt(){
			return `${this.data.msg}${this.data.num}`;
		}
	}
  }
  </script>

兄弟组件传值——vuex:(不仅仅局限于兄弟组件)

  • main.js
  import Vue from 'vue';
  import App from './App.vue';
  import router from './router';
  import store from './store';//引入

  Vue.config.productionTip = false;

  new Vue({
    router,
    store,//调用
    render: (h) => h(App),
  }).$mount('#app');
  • store/index.js
  import Vue from 'vue';
  import Vuex from 'vuex';

  Vue.use(Vuex);

  const num = {
      state: {//初始化值
            num:0,
      },
      getters:{//获取值
            num:state => state.num
      },
      mutations: {//设置值
            num:state => state.num++
      },
      actions: {//异步
          num ({ commit }) {
              setTimeout(() => {
                  commit('num')
              }, 1000)
          }
      }
  }
  export default new Vuex.Store({
    modules: {//模块儿
        num:num
    },
  });
  • 任意组件
  <template>
      <div id="app">
        <button @click="setVal">点击</button>
        <Home></Home>
      </div>
  </template>

  <script lang="ts">
    import Vue from 'vue';
    import vuex from 'vuex'
    import Home from '@/views/Home';

    export default Vue.extend({
      name: 'App',
      components: {
        Home
      },
      methods:{
          setVal(){
              this.$store.commit("num");//设置值
              console.log(this.$store.getters.num);//获取值
          }
      }
    });
    </script>
  • 更简单的获取方式:

一般情况下使用会报mapGetters is not defined的错误,先说解决方案吧!

  1.安装:npm isntall --save-dev  babel-preset-stage-3
  2.引入方法改写:import {mapGetters} from 'vuex';
  • 设置值的组件:
<template>
    <div id="app">
      <button @click="setVal">点击</button>
      <Home></Home>
    </div>
</template>

<script lang="ts">
  import Vue from 'vue';
  import vuex from 'vuex'
  import Home from '@/views/Home';

  export default Vue.extend({
    name: 'App',
    components: {
      Home
    },
    methods:{
        setVal(){
            this.$store.commit("num");
        }
    }
  });
  </script>
  • 获取值的组件:
  <template>
      <div class="sun">
          <p>{{num}}</p>
      </div>
  </template>

  <script>
      import {mapGetters} from 'vuex';
      export default {
          name: 'Sun',
          computed: {
              ...mapGetters(["num"])
          }
      }
  </script>

存在的问题:1. 页面刷新数据丢失;2.只在当前用户的浏览器中存在

兄弟组件通信EventBus

调用完之后必须销毁,否则会出现bug!!!

  • src/tools/event-bus.js(建文件)
  import Vue from 'vue'
  export const Bus = new Vue()
  • 事件总线:
  <template>
      <div id="app">
          <button @click="setVal">点击</button>
          <Home></Home>
      </div>
  </template>

  <script lang="ts">
      import Vue from 'vue';
      import {Bus} from '@/tools/event-bus'
      import Home from '@/views/Home';

      export default Vue.extend({
          name: 'App',
          components: {
              Home
          },
          data() {
              return {
                  msg: 0
              }
          },
          methods: {
              setVal() {
                  this.msg++;
                  Bus.$emit("share", this.msg);
              }
          }
      });
  </script>
  • 事件接收:
  <template>
      <div class="sun">
          <p>{{msg}}</p>
      </div>
  </template>

  <script>
      import { Bus } from '@/tools/event-bus'
      export default {
          name: 'Sun',
          data(){
              return {
                  msg:''
              }
          },
          methods:{
              setMsg(){
                  Bus.$on("share",(data)=>{
                      this.msg = data;
                  })
              }
          },
          created() {
              this.setMsg();
          },
          destroyed(){
              Bus.$off("share");
          }
      }
  </script>

版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者: 前端菜鸡的全桟之路 原文链接:https://juejin.im/post/6866788394614620168

回到顶部