前言

vue的组件传值分为三种方式:父传子、子传父、非父子组件传值

引用官网的一句话:父子组件的关系可以总结为 prop 向下传递,emit向上传递,兄弟之间用bus。
在这里插入图片描述

一、父子组件传值

子组件

<template>
    <div class="child">
        {{ message }}
    </div>
</template>

<script>
export default {
    name: "Child",
    props: {
        message: String,
    },
};
</script>

父组件

<template>
    <div class="father">
        <Child :message="text" />
        <input v-model="data" />
        <button @click="changeChild">点我改变子组件的值</button>
    </div>
</template>

<script>
import Child from "./Child";
export default {
    name: "Father",
    components: { Child },
    data() {
        return {
            data: "",
            text: "我是父组件的值",
        };
    },
    methods: {
        changeChild() {
            this.text = this.data;
        },
    },
};
</script>

效果图
在这里插入图片描述
改变后
在这里插入图片描述
详情可参考官网props

二、子组件通过emit来触发父组件的自定义事件

子组件

<template>
    <div class="child">
        <button @click="setTime">点击我获取父组件的方法</button>
    </div>
</template>

<script>
export default {
    name: "Child",
    methods:{
        setTime(){
            this.$emit("getTime","可以传参");
        }
    },
};
</script>

父组件

<template>
    <div class="father">
        <Child @get-time="getTime" />
        <input v-model="data" />
        <p>{{ time }}</p>
    </div>
</template>

<script>
import Child from "./Child";
import moment from "moment"   //npm i moment -s  下载日期插件
export default {
    name: "Father",
    components: { Child },
    data() {
        return {
            data: "",
            time: "",
        };
    },
    
    methods: {
        getTime(data) {
            this.time = moment().format('YYYY年MM月DD日, hh:mm:ss')
            this.data = data;
        },
    },
};
</script>

效果图
在这里插入图片描述
改变后
在这里插入图片描述
详情可看官网自定义事件

在父组件向子组件传递数据时,若是该数据为对象或数组,并且该对象或数组在父组件内部被修改,则 Vue 不会检测到。这种情况下,我们需要在父组件中设置一个临时变量来保存修改后的对象或数组,并将其传递给子组件。

关于父子组件传值遇到的坑可以看vue修改父组件传值报错

三、兄弟之间通过bus

父组件引入两兄弟

<template>
    <div class="father">
        <Child />
        <ChildTwo />
    </div>
</template>

<script>
import Child from "./Child";
import ChildTwo from "./ChildTwo";
export default {
    name: "Father",
    components: { Child, ChildTwo },
};

创建一个bus文件夹下面新建一个bus.js文件
bus.js代码

import Vue from 'vue'

var bus = new Vue();

export default bus;

兄弟组件一号

<template>
    <div class="child">
        <h1>我是1号兄弟组件</h1>
        <button @click="changeTwo">点击我改变2号的值</button>
    </div>
</template>

<script>
import Bus from "@/bus/bus"
export default {
    name: "Child",
    methods:{
        changeTwo(){
            Bus.$emit("changeName","可以选填的值")
        }
    },
};
</script>

兄弟组件二号

<template>
    <div class="child-two">
        <h1>我是2号兄弟组件</h1>
        <p>{{ name }}</p>
    </div>
</template>

<script>
import Bus from "@/bus/bus";
export default {
    name: "ChildTwo",
    data() {
        return {
            name: "uzi",
        };
    },
    mounted() {
        Bus.$on("changeName", (data) => { this.name = data });
    },
};
</script>

注:用bus传值,父组件引入子组件,子组件需要传值的用Bus. e m i t ( ) ,接收方用 B u s . emit(),接收方用 Bus. emit(),接收方用Bus.on()。
最后看效果图
在这里插入图片描述
改变后
在这里插入图片描述

四、其它方式传值传值

父孙传值

$attrs(向下)

官网是这么解释的
在这里插入图片描述
意思就是孙子组件的传值问题可以选择不使用props传值而通过$attrs传递

部分代码

//父组件
<template>
	<div class="father">
	  <compOne :message="message"/>
   </div>
</template>
<script>
import compOne from "@/views/Component/compOne";
export default {
  name: "father",
  components: {
    compOne,
  },
  data() {
    return {
      message: "父组件传过去的值",
    };
  },
  inheritAttrs: false,
  methods: { },
};
</script>

//子组件
<template>
  <div class="comp-one">
    <compOneChild v-bind="$attrs"/>
  </div>
</template>

<script>
import compOneChild from "./compOneChild.vue";
export default {
  name: "compOne",
  components: { compOneChild },
  inheritAttrs: false,
  created() {
    console.log("我是子组件", this.$attrs);
  },
  methods: {},
};
</script>

//孙子组件
<template>
  <div class="comp-one-child"> </div>
</template>

<script>
export default {
  name: "compOneChild",
  created() {
    console.log("我是孙组件", this.$attrs);
  },
  inheritAttrs: false,
};
</script>

打印结果
请添加图片描述

$listeners(向上)

官网是这么解释的
在这里插入图片描述
$listeners可以将孙组件的事件和参数传递给父组件

//父组件
<template>
	<div class="father">
	  <compOne
        v-on="$listeners"
        @compOneChild="compOneChild"/>
   </div>
</template>
<script>
import compOne from "@/views/Component/compOne";
export default {
  name: "father",
  components: {
    compOne,
  },
  data() {
    return { };
  },
  inheritAttrs: false,
  methods: { 
      compOneChild(val) {
      		console.log("我是父组件", val);
      },
    },
};
</script>

//子组件
<template>
  <div class="comp-one">
    <compOneChild  v-on="$listeners"/>
  </div>
</template>

<script>
import compOneChild from "./compOneChild.vue";
export default {
  name: "compOne",
  inheritAttrs: false,
  methods: {},
};
</script>

//孙子组件
<template>
  <div class="comp-one-child">
      <el-form ref="form" :model="form" label-width="80px">
      <el-form-item label="姓名">
        <el-input v-model="form.name"></el-input>
      </el-form-item>
      <el-form-item label="密码">
        <el-input v-model="form.pass"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="onSubmit">立即创建</el-button>
        <el-button>取消</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
export default {
  name: "compOneChild",
  data() {
    return {
      form: {
        name: "",
        pass: "",
      },
    };
  },
  inheritAttrs: false,
  methods: {
    onSubmit() {
      this.$listeners.compOneChild(this.form);
      //this.$emit("compOneChild", this.form);   //也可以用这种向上方式传值
    },
  },
};
</script>

打印结果
在这里插入图片描述

provide/inject

官网概念
这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。
在这里插入图片描述
官网链接provide / inject

用法举例

//祖先组件(刚登陆首页的组件)
  data() {
    return {
      userName: "李潇潇",
    };
  },
  provide() {
    return {
      newName: () => this.userName,
    };
  },
  //子孙组件(随便跳转详情的组件)
  inject: ["newName"],
  mounted() {
    console.log(this.newName());
    console.log(this.userName());
  },
  methods: {
    userName() {
      return this.newName();
    },
  }

在这里插入图片描述

最后看跳转子孙的打印值
在这里插入图片描述

parent/children

官网是这么介绍的
在这里插入图片描述
所以尽量少用,了解一下就行了。

五、VUEX传值

在使用VUEX时先弄懂几个概率。
VUEX是用来干嘛的?
答:vuex是一个状态管理工具存储应用所有组件的状态。
构成:

  • state:vuex的基本数据,用来存储变量。
  • mutations:提交更改数据,同步更新状态。
  • actions:提交mutations,可异步操作。
  • getters:是store的计算属性。
  • modules:模块,每个模块里面有四个属性。
    用官网上的一张图来展示vuex工作的流程
    在这里插入图片描述了解更多VUEX知识 可看官网What is Vuex?

实现的功能:有两个组件A和B,有一个公共的名字(默认为UZI),想要使组件A改变名字,组件B名字也改变为一样的,组件B改变反之A也改变。
在这里插入图片描述
这是文件目录,为了方便后期管理将store下面新建文件夹与文件,每个文件管理一个或几个状态,这里name.js管理name
在这里插入图片描述
store下面的index.js代码

import Vue from 'vue'
import Vuex from 'vuex'

import name from './name/name'

Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    name,
  }
})

name.js代码

const state = {       //基本数据,变量
    userName: "UZI" //默认值
}
const actions = {       //提交mutations
    changeNameOne({ commit }, name) {
        return commit("changeNameOne", name)
    },
    changeNameTwo({commit }, name) {
        return commit("changeNameOne", name)
    }
}
const getters ={     //计算属性
    userName(state){
        return  state.userName
    }
}
const mutations = {       //同步的数据
    changeNameOne(state, obj) {
        state.userName = obj
    },
    changeNameTwo(state, obj) {
        state.userName = obj
    },
}
export default {
    state,
    actions,
    getters,
    mutations
}

NameOne组件

<template>
    <div>
        <P class="title">组件A</P>
        <P class="titleName">名字:{{ userName }}</P>
        <div>
            <input v-model="name" placeholder="请输入名字" />
            <button @click="changeNameOne(name)">修改名字</button>
        </div>
    </div>
</template>

<script>
import { mapActions, mapGetters } from "vuex";
export default {
    name: "NameOne",
    data() {
        return {
            name: "JackLove",
        };
    },
    methods: {
        ...mapActions(
            ["changeNameOne"] //提交这个方法===this.$store.dispatch('changeNameTwo')
        ),
    },
    computed: {
        ...mapGetters(
            ["userName"] //计算属性===this.$store.getters.userName
        ),
    },
};
</script>

mapActions和mapGetters是vuex的语法糖

NameTwo组件

<template>
     <div>
        <P class="title">组件B</P>
        <P class="titleName">名字:{{ userName }}</P>
        <div>
            <input v-model="name" placeholder="请输入名字" />
            <button @click="changeNameTwo(name)">修改名字</button>
        </div>
    </div>
</template>

<script>
import { mapActions, mapGetters } from "vuex";
export default {
    name:"NameTwo",
    data() {
        return {
            name: "ClearLove",
        };
    },
    methods: {
        ...mapActions(
            ["changeNameTwo"] //提交这个方法===this.$store.dispatch('changeNameTwo')
        ),
    },
    computed: {
        ...mapGetters(
            ["userName"] //计算属性===this.$store.getters.userName
        ),
    },
}
</script>

最后看效果图,当修改A组件的名字的时候
在这里插入图片描述
当修改B组件的名字的时候
在这里插入图片描述

PS:最后再加了个组件C,看效果图
在这里插入图片描述
PS:还可以这样传参
this.$store.commit(‘name/changeNameOne’,res) (res是需要传的参数)

这样接收参数
this.$store.getters[“workStore/getToken”]
这种有没有方便
请添加图片描述

六、通过$refs获取实例

在这里插入图片描述
在这里插入图片描述

七、Storage传值

新建两个文件分别为setStorage.vue和getStorage.vue,一个用来储存一个用来获取数据。由于sessionStoragelocalStorage使用的方法一样这里用sessionStorage来做的示范。

先看页面
在这里插入图片描述
setStorage.vue组件

<template>
  <div>
      <input v-model="data" />
      <button @click="setData()">点击我分发数据</button>
  </div>
</template>

<script>
export default {
    name:"setStorage",
    data(){
        return{
            data:""
        }
    },
    methods:{
        setData(){
            sessionStorage.setItem('myData',this.data)   //用来储存data数据,myData自定义的名字
        }
    },
}
</script>

getStorage.vue组件

<template>
  <div>
      <label>{{data}}</label>
      <button @click="getData()">点击我获取数据</button>
  </div>
</template>

<script>
export default {
    name:"getStorage",
    data(){
        return{
            data:""
        }
    },
    methods:{
        getData(){
           let item= sessionStorage.getItem('myData')   //获取到myData储存的数据
           this.data=item   //赋值
        }
    },
}
</script>

效果图
在这里插入图片描述
首先要发送数据,然后才能获取得到,在网页中打开查看Application也可以查看到储存的数据

在这里插入图片描述
每天学习一点进步一点~~

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐