• 技术文章 >web前端 >前端问答

    vue组件怎么传值

    青灯夜游青灯夜游2023-01-06 17:26:16原创119

    传值方法:1、利用props实现父传子;2、子传父,需要自定义事件,在子组件中用“this.$emit(‘事件名’)”触发,而父中用“@事件名”监听;3、兄弟间,通过公有父元素作为桥接,结合父子props传参、子父自定义事件;4、用路由传值;5、用$ref传值;6、用依赖注入传给后代子孙曾孙;7、利用$attrs;8、借助$listeners中间事件;9、用$parent传等。

    本教程操作环境:windows7系统、vue3版,DELL G3电脑。

    本篇文章带大家聊聊vue组件传值的10种方式,常用的也有五六种,先上一张总结图:

    1.png

    1、父组件传给子组件

    在子组件里定义一个props,即props:[‘msg’],msg可以是对象也可以是基本数据类型

    如果你想定义一个默认值,即 props:{msg: {type: String, default: ‘hello world’}},
    若默认值是对象类型:props: { msg: { type: Object, default: () => { return { name: ‘dan_seek’ } } }}

    需要注意的是这种传值是单向的,你无法改变父组件的值(当然引用类型例外);而且如果直接修改props的值会报一个警告。

    推荐的写法是在data()里重新定义一个变量(见Children.vue),并把props赋值给它,当然计算属性也行。

    Children.vue

    <template>
        <section>
            父组件传过来的消息是:{{myMsg}}
        </section>
    </template>
    
    <script>
        export default {
            name: "Children",
            components: {},
            props:['msg'],
            data() {
                return {
                    myMsg:this.msg
                }
            },
            methods: {}
        }
    </script>

    Parent.vue

    <template>
      <div class="parent">
        <Children :msg="message"></Children>
      </div>
    </template>
    
    <script>
    import Children from '../components/Children'
    
    export default {
      name: 'Parent',
      components: {
          Children
      },
      data() {
          return {
              message:'hello world'
    }
    },
    }
    </script>

    2、子组件传给父组件

    这里需要使用自定义事件,在子组件中使用this.$emit(‘myEvent’) 触发,然后在父组件中使用@myEvent监听

    Children.vue

    <template>
        <div class="parent">
            这里是计数:{{parentNum}}
            <Children-Com @addNum="getNum"></Children-Com>
        </div>
    </template>
    
    <script>
        import ChildrenCom from '../components/Children'
    
        export default {
            name: 'Parent',
            components: {
                ChildrenCom
            },
            data() {
                return {
                    parentNum: 0
                }
            },
            methods:{
                // childNum是由子组件传入的
                getNum(childNum){
                    this.parentNum = childNum
                }
            }
        }
    </script>

    Parent.vue

    <template>
        <div class="parent">
            这里是计数:{{parentNum}}
            <Children-Com @addNum="getNum"></Children-Com>
        </div></template><script>
        import ChildrenCom from '../components/Children'
    
        export default {
            name: 'Parent',
            components: {
                ChildrenCom        },
            data() {
                return {
                    parentNum: 0
                }
            },
            methods:{
                // childNum是由子组件传入的
                getNum(childNum){
                    this.parentNum = childNum            }
            }
        }</script>

    3、兄弟组件间传值

    运用自定义事件emit的触发和监听能力,定义一个公共的事件总线eventBus,通过它作为中间桥梁,我们就可以传值给任意组件了。而且通过eventBus的使用,可以加深emit的理解。

    EventBus.js

    import Vue from 'vue'
    export default new Vue()

    Children1.vue

    <template>
        <section>
            <div @click="pushMsg">push message</div>
            <br>
        </section>
    </template>
    
    <script>
        import eventBus from './EventBus'
        export default {
            name: "Children1",
            components: {},
            data() {
                return {
                    childNum:0
                }
            },
            methods: {
                pushMsg(){
                	// 通过事件总线发送消息
                    eventBus.$emit('pushMsg',this.childNum++)
                }
            }
        }
    </script>

    Children2.vue

    <template>
        <section>
            children1传过来的消息:{{msg}}
        </section>
    </template>
    
    <script>
        import eventBus from './EventBus'
    
        export default {
            name: "Children2",
            components: {},
            data() {
                return {
                    msg: ''
                }
            },
            mounted() {
            	// 通过事件总线监听消息
                eventBus.$on('pushMsg', (children1Msg) => {
                    this.msg = children1Msg
                })
            }
        }
    </script>

    Parent.vue

    <template>
        <div class="parent">
            <Children1></Children1>
            <Children2></Children2>
        </div>
    </template>
    
    <script>
        import Children1 from '../components/Children1'
        import Children2 from '../components/Children2'
    
        export default {
            name: 'Parent',
            components: {
                Children1,
                Children2
            },
            data() {
                return {
                }
            },
            methods:{
            }
        }
    </script>

    github上还有一个开源vue-bus库,可以参考下: https://github.com/yangmingshan/vue-bus#readme

    4、路由间传值

    i.使用问号传值

    A页面跳转B页面时使用 this.$router.push(‘/B?name=danseek’)

    B页面可以使用 this.$route.query.name 来获取A页面传过来的值

    上面要注意router和route的区别

    ii.使用冒号传值

    配置如下路由:

    {
        path: '/b/:name',
        name: 'b',
        component: () => import( '../views/B.vue')
      },

    在B页面可以通过 this.$route.params.name 来获取路由传入的name的值

    iii.使用父子组件传值

    由于router-view本身也是一个组件,所以我们也可以使用父子组件传值方式传值,然后在对应的子页面里加上props,因为type更新后没有刷新路由,所以不能直接在子页面的mounted钩子里直接获取最新type的值,而要使用watch。

    <router-view :type="type"></router-view>
    // 子页面
    ......
    props: ['type']
    ......
    watch: {
                type(){
                    // console.log("在这个方法可以时刻获取最新的数据:type=",this.type)
                },
            },

    5、使用$ref传值

    通过$ref的能力,给子组件定义一个ID,父组件通过这个ID可以直接访问子组件里面的方法和属性

    首先定义一个子组件Children.vue

    <template>
        <section>
            传过来的消息:{{msg}}
        </section>
    </template>
    
    <script>
        export default {
            name: "Children",
            components: {},
            data() {
                return {
                    msg: '',
                    desc:'The use of ref'
                }
            },
            methods:{
                // 父组件可以调用这个方法传入msg
                updateMsg(msg){
                    this.msg = msg
                }
            },
        }
    </script>

    然后在父组件Parent.vue中引用Children.vue,并定义ref属性

    <template>
        <div class="parent">
            <!-- 给子组件设置一个ID ref="children" -->
            <Children ref="children"></Children>
            <div @click="pushMsg">push message</div>
        </div>
    </template>
    
    <script>
        import Children from '../components/Children'
    
        export default {
            name: 'parent',
            components: {
                Children,
            },
            methods:{
                pushMsg(){
                    // 通过这个ID可以访问子组件的方法
                    this.$refs.children.updateMsg('Have you received the clothes?')
                    // 也可以访问子组件的属性
                    console.log('children props:',this.$refs.children.desc)
                }
            },
        }
    </script>

    6、使用依赖注入传给后代子孙曾孙

    假设父组件有一个方法 getName(),需要把它提供给所有的后代

    provide: function () {
      return {
        getName: this.getName()
      }
    }

    provide 选项允许我们指定我们想要提供给后代组件的数据/方法

    然后在任何后代组件里,我们都可以使用 inject 来给当前实例注入父组件的数据/方法:

    inject: ['getName']

    Parent.vue

    <template>
        <div class="parent">
            <Children></Children>
        </div>
    </template>
    
    <script>
        import Children from '../components/Children'
    
        export default {
            name: 'Parent',
            components: {
                Children,
            },
            data() {
                return {
                    name:'dan_seek'
                }
            },
            provide: function () {
                return {
                    getName: this.name
                }
            },
        }
    </script>

    Children.vue

    <template>
        <section>
            父组件传入的值:{{getName}}
        </section>
    </template>
    
    <script>
        export default {
            name: "Children",
            components: {},
            data() {
                return {
                }
            },
            inject: ['getName'],
        }
    </script>

    7、祖传孙 $attrs

    正常情况下需要借助父亲的props作为中间过渡,但是这样在父亲组件就会多了一些跟父组件业务无关的属性,耦合度高,借助$attrs可以简化些,而且祖跟孙都无需做修改

    GrandParent.vue

    <template>
        <section>
            <parent name="grandParent" sex="男" age="88" hobby="code" @sayKnow="sayKnow"></parent>
        </section>
    </template>
    
    <script>
        import Parent from './Parent'
        export default {
            name: "GrandParent",
            components: {
              Parent
            },
            data() {
                return {}
            },
            methods: {
              sayKnow(val){
                console.log(val)
              }
            },
            mounted() {
            }
        }
    </script>

    Parent.vue

    <template>
      <section>
        <p>父组件收到</p>
        <p>祖父的名字:{{name}}</p>
        <children v-bind="$attrs" v-on="$listeners"></children>
      </section>
    </template>
    
    <script>
      import Children from './Children'
    
      export default {
        name: "Parent",
        components: {
          Children
        },
        // 父组件接收了name,所以name值是不会传到子组件的
        props:['name'],
        data() {
          return {}
        },
        methods: {},
        mounted() {
        }
      }
    </script>

    Children.vue

    <template>
      <section>
        <p>子组件收到</p>
        <p>祖父的名字:{{name}}</p>
        <p>祖父的性别:{{sex}}</p>
        <p>祖父的年龄:{{age}}</p>
        <p>祖父的爱好:{{hobby}}</p>
    
        <button @click="sayKnow">我知道啦</button>
      </section>
    </template>
    
    <script>
      export default {
        name: "Children",
        components: {},
        // 由于父组件已经接收了name属性,所以name不会传到子组件了
        props:['sex','age','hobby','name'],
        data() {
          return {}
        },
        methods: {
          sayKnow(){
            this.$emit('sayKnow','我知道啦')
          }
        },
        mounted() {
        }
      }
    </script>
    显示结果
    父组件收到
    祖父的名字:grandParent
    子组件收到
    祖父的名字:
    祖父的性别:男
    祖父的年龄:88
    祖父的爱好:code

    8、孙传祖

    借助$listeners中间事件,孙可以方便的通知祖,代码示例见7

    9、$parent

    通过parent可以获父组件实例,然后通过这个实例就可以访问父组件的属性和方法,它还有一个兄弟root,可以获取根组件实例。

    语法:

    // 获父组件的数据
    this.$parent.foo
    
    // 写入父组件的数据
    this.$parent.foo = 2
    
    // 访问父组件的计算属性
    this.$parent.bar
    
    // 调用父组件的方法
    this.$parent.baz()

    于是,在子组件传给父组件例子中,可以使用this.$parent.getNum(100)传值给父组件。

    10、sessionStorage传值

    sessionStorage 是浏览器的全局对象,存在它里面的数据会在页面关闭时清除 。运用这个特性,我们可以在所有页面共享一份数据。

    语法:

    // 保存数据到 sessionStorage
    sessionStorage.setItem('key', 'value');
    
    // 从 sessionStorage 获取数据
    let data = sessionStorage.getItem('key');
    
    // 从 sessionStorage 删除保存的数据
    sessionStorage.removeItem('key');
    
    // 从 sessionStorage 删除所有保存的数据
    sessionStorage.clear();

    注意:里面存的是键值对,只能是字符串类型,如果要存对象的话,需要使用 let objStr = JSON.stringify(obj) 转成字符串然后再存储(使用的时候 let obj = JSON.parse(objStr) 解析为对象)。

    这样存对象是不是很麻烦呢,推荐一个库 good-storage ,它封装了sessionStorage ,可以直接用它的API存对象

    // localStorage
     storage.set(key,val) 
     storage.get(key, def)
     
     // sessionStorage
     storage.session.set(key, val)
     storage.session.get(key, val)

    更多请移步:https://github.com/ustbhuangyi/storage#readme

    【相关推荐:vuejs视频教程web前端开发

    以上就是vue组件怎么传值的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:Vue vue组件传值
    上一篇:object.assign()怎么用 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • vue二级路由报错怎么办• vue能实现自适应吗• vue怎么禁止返回到上一页• vue打包刷新报错怎么办• 一文带你详解Vue中的组件化编程• 一文详解vue怎么实现v-model(附代码示例)
    1/1

    PHP中文网