zoukankan      html  css  js  c++  java
  • Vue组件之间通信

    vue组件传值有以下几种情况: 父组件向子组件传值、子组件向父组件传值、兄弟组件之间传值等

    一、父组件向子组件传值:

      传值方式: props

    <father>
        // 动态传递值
        <son :data="msg"></son> // 子组件son
       // 静态传值
        <son2 data="这是传递静态值"></son2>
    </father>
    
    // 父组件
    <script>
    export default {
         data() {
            msg: '向子组件传值'
         }
    
    }
    </script>
    
    // 子组件 -- son
    <script>
    export default {
       props: {
            msg: {
               type: String, // 基础类型检查
               required: true   // 是否必传值
            }
       },
       data() {
           str: this.msg   // 也可以将传递过来的值定义在data中
       }     
    }
    </script>
            

      1:prop的大小写: HTML中的attribute名对大小写不敏感,所以prop中的驼峰值需要等价于短横线命名;如果使用字符模板,就没有这个问题了

    // 在HTML中
    <component :my-data="data"></component>
    
    // 在props与之对应的为驼峰命名
    props: ['myData']

      2:prop的类型:

    // 官方给的例子
    props: ['title', 'likes', 'isPublished', 'commentIds', 'author']
    
    // 但是,通常希望每个prop都有指定的类型,这时,可以使用对象形式列出prop,这些property的名称和值分别是prop各自的名称和类型;
        props: {
            title: String,
            likes: Number,
            isPublished: Boolean,
            comments: Array,
            author: Object,
            callback: Function,
            contractPromise: Promise  
        }

      3: 单项数据流

      所有的prop都使得其父子之间形成一个单行向下行绑定:父组件的更新会向下流动到子组件中,但是反过来不行;当父组件更新时,子组件中所有的props都是最新值,所以不应该在子组件中更新props;

      两种常见的试图更改一个prop的情形:

        #这个prop用来传递一个初始值;这个子组件接下来希望将其作为一个本地的prop数据来使用:这种情况下,最好定义一个本地data property并将这个prop用做其初始值; 

    props: ['data'],
    data() {
       return {
          msg: this.data
       }
    }

        #这个prop以一种原始的值传入且需要进行转换:在这种情况下,最好使用这个prop的值来定义一个计算属性:

    props:['size'],
    // 计算属性
    computed: {
       normalizedSize: function() {
           return this.size.trim().toLowerCase()
       }
    }

       注意:js中对象和数组是通过应用传入的,所以对于一个数组或者对象类型的prop来说,在子组件中改变变更这个对象或数组本身将会影响到父组件的值

      4: 其他详情参考官方文档

    二、子组件向父组件传值:

      通过自定义事件传值;

    // 通过 this.$emit()自定义事件触发
    // ====== 子组件
    <template>
        <div>
             <button @click="emitToFather">点击向父组件传值</button>
        </div>
    </template>
    <script>
       export default {
          name: 'Son',
          data() {
             return {
                msg: '向父组件传的值'
             }
           },
           methods: {
               emitToFather() {
                   //  getDataFromSon 是自定义事件名
                   this.$emit('getDataFromSon', this.msg)
                }
           }
       }
    </script>
    // ====== 父组件
    <template>
        <div>
           //  事件名需要完全匹配才可以
           <son @getDataFromSon="getDataFromSon"><son>
        </div>
    </template>
    <script>
       export default {
          name: 'Father',
          data() {},
           methods: {
               getDataFromSon(val) {
                 // val 就是从子组件传递过来的值
                }
           }
       }
    </script>

    三、兄弟之间组件传值:

       通过eventBus或者vuex进行传值;

       vue没有直接子传子的方法,如果一定需要兄弟之间传参,可以先传到父组件,再传到子组件。  

    // 通过eventBus(即通过on监听,emit触发的方式)
    // eventBus.js  定义一个新的vue实例,专门用于传递数据,并导出
    import Vue from 'vue'
    export default new Vue()
    
    // 定义传递的方法名和传输内容,点击事件或钩子函数eventBus.emit事件
    // componentA.vue
    <template>
      <div>
           <button @click="emitToB">点击传递数据给兄弟组件B</button>
      </div>
    </template>
    <script>
    import eventBus from 'common/js/eventBus.js'
    export default {
       methods: {
          emitToB() {
             //  也可以在全局挂载eventBus即vue实例。通过this调用
             eventBus.$emit('eventFromA', 'A传递给B组件的值') // 定义方法名和要传输的数据
          }
       }
    }
    </script>
    // componentB
    <template>
      <div>{{ title }}</div>
    </template>
    <script>
    import eventBus from 'common/eventBus.js'
    export default {
       data() {
         return { title: '' }
       },
        mounted() { this.getEventData }, // 可以在created或者mounted钩子函数中调用
       methods: {
         getEventData() {
             //  区分this指向那个vue实例
             const that = this
             //  eventFromA是自定义的事件名和传递时保持一致
             eventBus.$on('eventFromA', function(val) {
                that.title = val  // val  就是A组件传递过来的值
                // this.title = val  此处this指向eventBus的vue实例
             })
          }
       }
    }
    </script>    

      # 大项目时使用vuex进行数据传递:详情: https://baijiahao.baidu.com/s?id=1618794879569468435&wfr=spider&for=pc

    四、1:通过路由带参数进行传值

        A组件传值写法:this.$router.push({ path: '/componentB', query: { id: 2 } }) // 跳转到B

        B组件取值写法: this.$route.query.id

        注意:

        1:Vue路由导航有两种方法:声明式导航<router-link :to="...">和编程式导航 router.push(...)

        2:页面跳转有push和replace两种方式

        # this.$router.push(): 描述:跳转到不同的url这个方法会向history栈添加一个记录,点击后退会返回上一个页面

        #this.$touter.replace() 描述:同样是跳转到指定的url,但是这个方法不会向history栈中添加新的记录,点击返回,会跳转到上上一个页面,上一个记录是不会存在的。

        #this.$touter.go(n) 相对于当前页面向前或者向后跳转多少个页面,类似于window.history.go(n)

        3:传参的方式又分为查询参数query(+path) 和命名路由params(+name)两种方式:

         #命名路由搭配params,刷新页面会参数丢失;

         #查询参数搭配query,刷新页面数据不会丢失;

           接收参数使用this.$router后面就是搭配路由的名称就能获得取到的参数

      2:通过设置session Stroage缓存的形式进行传递

        两个组件A和B,在组件中设置缓存orderData

        const orderData = { 'orderData': 123 }

             sessionStorage.setItem('缓存名称', JSON.stringify(orderData))

        B组件就可以获取在A中设置的缓存了

        const dataB = JSON.parse(sessionStorage.getItem(‘缓存名称’))

    五、.sync修饰符

      在有些情况下,我们可能需要对一个prop进行双向数据绑定,推荐使用update:myPropName的模式进行触发事件取而代之。

    // 举个例子
    在一个包含title prop的假设的组件中,我们可以用以下方法表达对其赋值的意图
        this.$emit('update:title', newTitle)
    // 为了方便起见,我们为这中模式提供一个缩写,即.sync修饰符
        <text-document :title.sync='title'></text-document>

    官方文档:https://cn.vuejs.org/v2/guide/components-props.html

  • 相关阅读:
    过滤器
    自定义指令
    Window setTimeout() 方法
    Window setInterval()方法
    ThingJS官方案例(五):物联网室内3D定位导航,上下楼怎么办?
    基于WebGL的虚拟太阳系漫游技术实现 ThingJS 科幻片
    ThingJS官方案例(四):快速应用3D场景下的模拟导航能力
    ThingJS官方示例(三):3D标记“Marker”跳跃、闪烁和发光动画效果
    ThingJS官方示例(二):利用电子标注判断物联网设备的位置
    ThingJS 官方示例(一):禁区告警的3D电子围栏可视化
  • 原文地址:https://www.cnblogs.com/xsk-walter/p/12765305.html
Copyright © 2011-2022 走看看