Vue 组件传值的12种方法

1. 父传子

1. props

**父组件是通过props属性给子组件通信的数据是单向流动 父—>子 **

子组件不能修改props 否则报错

实现步骤

1.子组件在props 创建一个属性,用于接收传输的值
2.父组件 引入子组件 - 注册子组件 - 引用子组件
3.父组件 在 子组件上 创建动态属性
4.将传递的值 赋值给 对应的动态属性

props 接收传值

  • 父组件
<template>
	<div>
        <h2>{{msg}}h2>
         
        <Son :msg="msg">Son>
    div>
template>
<script>
// 1. 引入子组件
import Son from './Son'
//2.注册子组件
export default {
   name: 'Parent',
   data () {
     return {
       msg: '父组件',
     }
   },
   components:{Son},
}
script>
  • 子组件
    • props 有三种接收数据的方式
      1. 数组字符型 [‘msg’,‘num’]
      2. 对象型 { msg{ type:String,required: true } }
<template>
	<div>
        <h2>子组件h2>
        <div>{{msg}}给子组件传值div>
    div>
template>
<script>
export default {
   name: 'Son',
   // 接收父组件传递的值
   // 数组字符型
   props:['msg'],
   // 对象型
   props:{
       msg{
           type:String,
           required: true// 非空
           default: “子组件”  // 默认值
   		}
   }
}
script>

2. 子传父

父组件 通过绑定自定义事件,接收子组件传递过来的参数

子组件 通过调用$emit 来触发父组件上的自定义事,从而实现传参

实现步骤

1.父组件在子组件标签上传入一个自定义事件
2.子组件通过$emit触发事件
3.$emit 第一个参数是事件名称,第二个参数是传入的参数
4.父组件事件函数中,接收传递的参数参与执行
  • 父组件
 <template>
   <div>
     <h2>父组件h2>
     <Son  @getData="getState">Son> 
      
   div>
 template>
 <script>
 import Son from './Son'
 export default {
   name: 'Parens',
   data () {
     return {
       msg: '父组件'
     }
   },
   components:{Son},
   methods:{
     getState(state){
         console.log(state) // 子组件 $emit 调用 父组件 getState 传递 state 参数
		}
   }
 }
 script>
  • 子组件
<template>
   <div >
     <div>
         子组件
    div>
     <button @click="setData">传值button>
   div>
 template>
 <script>
 export default {
   name: "Son",
   data(){
     return {
         state:"我是子组件"
     }
   },
   methods:{
     setData:function(){
       this.$emit('getData',this.state)//触发getData方法,this.state 为向父组件传递的数据
     }
   }
 }
 script>

3. 非父子

1. provide 和 inject

祖 --> 父孙

祖组件

<template>
  <div>
    <h2>我是父组价h2>
    <div>我的数据有{{time}},{{name}},{{num}}div>
      // 通过事件修改 num 值
    <button @click="ReviseState">修改一下button>
    <ComA />
  div>
template>

<script>
import ComA from './components/ComA.vue'
export default {
  name: 'VueApp',

  data () {
    return {
      time: "2022-1-1",
      name: "张三",
      num: 30
    };
  },
  methods: {
    ReviseState () {
      this.num++
    }
  },
  components: {
    ComA
  },
  provide () {	// 传递给子孙组件 数据
    return {
      num: this.num,
      time: this.time
    }
  }
};
script>

父组件

<template>
  <div>
    <h2>ComAh2>
    <div>{{num}},{{time}}div>
    <ComB />
  div>
template>

<script>
import ComB from './ComB.vue'
export default {
  name: 'VueComA',
  inject: ['num', "time"],	// 接收父组件传递的数据
  components: {
    ComB
  }
};
script>

孙组件

<template>
  <div>
    <h2>ComBh2>
    <div>我继承了{{num}},{{time}}div>
  div>
template>

<script>
export default {
  name: 'VueComB',
  inject: ['num', "time"]	// 接收祖组件传递的 数据
};
script>

Vue 组件传值的12种方法_第1张图片

当我们点击按钮 修改祖组件的数据
Vue 组件传值的12种方法_第2张图片

祖组件修改了,子孙组件没有改变,这是因为在provide中引入数据本身并不是响应式的,所以我们可以使用一些响应式的API来完成这些功能,比如computed函数。而且在调用的时候,因为computed返回的是一个ref对象,我们要取出value属性来使用。

import {computed} from 'vue'
provide () {	// 传递给子孙组件 数据
    return {
      num: computed(()=> this.num),	// 使用 computed 使传递的数据具有响应式
      time: this.time
    }
  }

Vue 组件传值的12种方法_第3张图片

2. mitt 库

全局事件总线可以用于非父子组件之间的通信,如与兄弟组件/兄弟组件的子组件进行通信。

先订阅 --> 再发布

全局传值

  • 安装

    npm install mitt
    
  • 创建 mitt

    import mitt from 'mitt';
    const emitter = mitt();
    export default emitter;
    
  • 组件A 传递数据 — 发布

    <template>
      <div>
        <h2>ComAh2>
        <div>{{num}}--{{uname}}div>
        
        <button @click="setData">发送请求button>
        <button @click="getnum">num++button>
        <ComB />
      div>
    template>
    
    <script>
    import emitter from './mitt'
    export default {
      name: 'VueComA',
      data () {
        return {
          num: 1,
          uname: '张三'
        }
      },
      methods: {
          // 组件A 定义一个发起数据的事件
        setData () {
          // 发布
          emitter.emit('setData', { num: this.num, name: this.uname })
        },
        getnum () {
          this.num++
        }
      }
    };
    script>
    
  • 组件A 接收数据 — 订阅

    <template>
      <div>
        <h2>ComBh2>
        <div>{{num}}--{{uname}}div>
      div>
    template>
    
    <script>
    import emitter from './mitt'
    export default {
      name: 'VueComB',
      data () {
        return {
          num: 0,
          uname: '李四'
        }
      },
      created () {
      // 接收传值数据 	-- 订阅
        emitter.on("setData", (data) => {
          console.log(data);
          this.uname = data.name
          this.num = data.num
        })
      }
    };
    script>
    
    

3. pusbub 库

全局传值

全局事件总线可以用于非父子组件之间的通信,如与兄弟组件/兄弟组件的子组件进行通信。

先订阅 --> 再发布

(与mitt 类似 – 不需要定义中间件)

  • 安装

    npm i pubsub-js --save-dev
    
  • 组件A 传递数据 — 发布

    import PubSub from 'pubsub-js'
    // 发布
    setData () {
          PubSub.publish('setData', { num: this.num, name: this.uname })
    },
    
  • 组件B 接收数据 — 接收

    <script>
    import PubSub from 'pubsub-js'
      // 订阅						第一个参数是 监听标识(_)占位符	第二个参数是传递参数
      PubSub.subscribe("setData", (_, data) => {
              console.log(data);
              this.uname = data.name
              this.num = data.num
          })
      }
    script>
    
    

4. Bus 总线程

bus总线程 在vue3中已经废弃了

类似 mitt 和 pusbub

全局传值

  • 配置
new Vue({
  render: h => h(App),
  beforeCreate() {
    //挂载全局事件总线 $bus
    Vue.prototype.$bus = this;
 },
}).$mount('#app');
  • 组件A 传递数据 — 发布

     this.$bus.$emit('setData', { num: this.num, name: this.uname })
    
  • 组件B 接收数据 — 接收

    this.$bus.$on('setData', (data) => {
          this.uname = data.name
          this.num = data.num
    })
    

5. v-model

父组件通过v-model传递值给子组件时,会自动传递一个value的prop属性,在子组件中通过this.$emit(“input”,val)自动修改v-model绑定的值

父传子 子改父

  • 父组件 传递数据 – 不是响应式

    <template>
      <div>
        <h2>我是父组价h2>
        <div>{{num}}div>
        <ComA v-model="num" />
        <button @click="ReviseState">修改一下button> // 数据修改后 子组件不会有影响
      div>
    template>
    <script>
    import ComA from './components/ComA.vue'
    export default {
      name: 'VueApp',
      data () {
        return {
          time: "2022-1-1",
          name: "张三",
          num: 30
        };
      },
      methods: {
        ReviseState () {
          this.num++
        }
      },
      components: {
        ComA,
        ComB
      },
    };
    script>
    
  • 子组件 接收数据 子组件可以修改父组件传递值

    <template>
      <div>
        <h2>ComAh2
         type="text"
               v-model="num"
               @change="setData">
        
      div>
    template>
    
    <script>
    export default {
      name: 'VueComA',
      data () {
        return {
          num: 0,
        }
      },
     // 接收父级的传递的参数
      props: {
        value: Number
      },
      created () {
        this.num = this.value
      },
      methods: {
        setData () {
        // 修改父级数据
          this.$emit('input', this.num);
        }
      }
    };
    script>
    <style lang="scss" scoped>
    style>
    

6. vuex 全局状态管理

全局传值

1--vuex注意事项:
	不允许通过方法直接操作state
    只能通过mutation 改变 state中的数据, 集中监听数据的实时变化

2--State 数据
	$store.state.xxx 参数
	通过 import { mapState } from 'vuex' 映射 接收 state的值
	必须在 computed 中 ...mapState(['xxx']) xxx 字符串

3--Mutations 操作数据、
	this.$store.commit('xxx', 参数)
	import { mapMutations } from 'vuex' 映射 接收 mutations同步方法
	必须在 methods 中 ...mapMutations(['xxx'])  带参数 调用时 xxx(参数)

4--Action 调用 Action 异步方法 触发 Mutations 操作 同步方法
	this.$store.dispatch('xxx', 参数)
	import { mapActions } from 'vuex' 映射 接收 Action异步方法
	必须在 methods 中 ...mapActions(['xxx']) 带参数 调用时 xxx(参数)

5--Getters getters 对 state 进行监听
	this.$store.getters.xxx
	import { mapGetters } from 'vuex' 映射 接收 Getter 监听方法
	必须在 computed 中 ...mapGetters(['xxx'])

6--modules 模块化
	通过模块 私有化
	模块调用  $store.state.模块名.参数
	...mapState(['模块名'])


关于mutations 操作数据
	1--定义state中数据操作方法
	2--this.$store.commit(事件名称)

7. ref

子传父 父控制子

  • 父组件
<ComA ref="msg" />	-- 给子组件设置属性 ref=""

this.$refs.msg	// 通过调用 $refs.xxx 获取到 子组件的组件实例 直接操作子组件订单方法和数据

8. 路由(Route)传值

利用路由跳转实现跨组件传值

1. 动态传参

- 传参
    - router-link 路由导航

        <router-link to = "/跳转路径/传入的参数"></router-link>

    - 编程式导航 
        this.$router.push({
            path:"/跳转路径/传入的参数"
        })
        
- 接收参数
this.$route.params.xxx 

2. params 传值

- 传值
this.$router.push({
		path:"/跳转路径",
        params: {	// 传参
          name: '张三'
        }
      })
      
- 接收参数
this.$route.params.xxx 

3. query传值

- 传值
this.$router.push({
        path: '/跳转路径',
        query: {
          name: '张三'
        }
      })

- 接收参数
this.$route.query.xxx 

9. 缓存

利用缓存实现跨组件传值
全局传值

1. Cookie

  • 特性
 	   存储特效:  可以设置缓存时间,关闭浏览器 清除Cookie
       大小特效:  存储大小 4kb左右 (20条左右信息)
       服务通信:  用于携带 会话秘钥token值 等 剪短的字符串
       特性:      数据保存在本地服务器  本地服务才能读取  可跨域	参与服务器交互
       读写操作:  
               -:  生成cookie 需要键值对 才能生成多个
                      诺不然 会产生覆盖
                      document.cookie = 'aa=我是一个cookie'
                      cookie.setMaxAge(2000) // 设置 生命周期
                      document.cookie = 'aa=我是一个cookie;expires=+'new Date(Date.parse(new Date())+添加时间).+'

              -:  
                      将cookie 时间改成过去时
                      document.cookie = "name=; expires="+ 过去时间+";"
                      Cookies.remove('name');
 
               -:  
                      键值对对应 覆盖(修改)
                      document.cookie = "name=1"  添加 键值不存在
                      document.cookie = "name=2"  修改 键值相同
        
        安全问题: 添加时 设置 HttpOnly  只允许指定域名读取
        
                  - cookies保存数据语法:
                        function setCookie(name,value)
                        {
                            var Days = 3;
                            var exp = new Date();
                            exp.setTime(exp.getTime() + Days*24*60*60*1000);
                            document.cookie = name + "="+ escape (value) + ";expires=" + exp.toGMTString();
                        }
                  - cookies读取数据语法:
                        function getCookie(name)
                        {
                            var arr,reg=new RegExp("(^| )"+name+"=([^;]*)(;|$)");
                            if(arr=document.cookie.match(reg))
                            return unescape(arr[2]);
                            else
                            return null;
                        }

                  - cookies删除数据语法:
                        function delCookie(name)
                        {
                            var exp = new Date();
                            exp.setTime(exp.getTime() - 1);
                            var cval=getCookie(name);
                            if(cval!=null)
                                document.cookie= name + "="+cval+";expires="+exp.toGMTString();
                        }
  • 传值

    - 传入
    document.cookie = '张三'
    
    - 获取
    name = document.cookie
    

2. sessionStorage

  • 特性
	   存储特效:  关闭当前会话(页面),或者浏览器 清除session     仅保存在当前页面
       大小特效:  存储大小 一般5M左右(根据浏览器不同决定)
       特效:      数据保存 当前页面
       读写操作:
              -: 生成sessionStorage 需要键值对方式
                    sessionStorage.setItem("name","1")
              -: 
                    sessionStorage.removeItem("数据名") // 删除一条
                    sessionStorage.clear()             // 删除全部
              -: 
                    sessionStorage.setItem("name","1")  添加 键值不存在
                    sessionStorage.setItem("name","2")  修改 键值相同
              -: 
              		sessionStorage.getItem("name"
  • 传值

    - 传入
    sessionStorage.setItem("健名","值")
    
    - 获取
    sessionStorage.getItem("健名"

3. localStorage

  • 特性
	   存储特效:  添加后 不手动清除,就不会消失
       大小特效:  和 sessionStorage 类似
       特性:      数据保存在本地内存 
       读写操作:  
              -:
                    localStorage.setItem("name","1");
                    localStorage.getItem("name")
              -:
                    localStorage.removeItem("name")
                    localStorage.clear()   
              -: 
                    localStorage.setItem("name","1"); // 增 键值不存在
                    localStorage.setItem("name","2"); // 改 键值相同
              -: 
              		localStorage.getItem("name"
  • 传值

    - 传入
    localStorage.setItem("健名","值")
    
    - 获取
    localStorage.getItem("健名"

10. $attr

祖孙传值

父传子 -> 子级在自己的子组件上设置 v-bind=“$attr” --> 孙组件 接收父组件没有接收的值

  • 祖组件

    <ComA :num="num" :uname="uname" />	- 传递俩个参数
    
    data () {
        return {
          uname: "张三",
          num: 30
    }
    
  • 父组件

    <ComB v-bind="$attrs" />	- 父组件设置 v-bind="$attrs" 将剩余参数传给下一个组件
    
    props: {
        num: Number
     },
    
  • 孙组件

    props: {
        uname: String,	// 张三
        num: Number	// undefined		父组件拦截了 num值 所以子组件undf
      },
    

11. $listeners

孙祖传值

祖组件绑定自定义事件 --> 父组件 绑定自定义事件 v-on=“$listeners” --> 孙组件通过 $ $emit 触发祖组件自定义事件实现传值

  • 祖组件

    <ComA @event="event" /> -- 给子组件绑定自定义事件
    
     methods: {
        event (value) { // 接收孙组件的传值
          console.log(value);
    }
      },
    
  • 子组件

     -- 设置 v-on="$listeners" 将祖组件的自定义函数传递给子组件
    
  • 孙组件

     <button @click="setData">按钮button> -- 触发祖组件事件 实现传值
      methods: {
        setData () {
          this.$emit('event', '传参')	// 传参
        }
      }
    

12. 设置全局变量

在vue实例原型中 存放数据

你可能感兴趣的:(vue.js,javascript,前端)