• vue中父子传值及vue中$refs、$emit、$on、$parent、$children使用的理解


    一 子传父(对$emit的理解)

    作用
    子组件可以使用 $emit 触发父组件的自定义事件。
    语法
    vm.$emit( event, arg ) //触发父级实例上的事件
    对于vue.js中的this.emit的理解:
    举例 : this.emit(‘increment1’,”加参数”);
    其实它的作用就是触发自定义函数。此外,可以子组件传参数给父组件
    综述,即子组件调用父组件的方法并传递数据
    具体应用如下

    子组件

    <template>
      <button @click="emitEvent">点击我</button>
    </template>
    <script>
      export default {
        data() {
          return {
            msg: "我是子组件中的数据"
          }
        },
        methods: {
          emitEvent(){
            this.$emit('my-event', this.msg)
            //通过按钮的点击事件触发方法,然后用$emit触发一个my-event的自定义方法,传递this.msg数据。
          }
        }
      }
    </script>

    父组件

    <template>
      <div id="app">
        <child-a @my-event="getMyEvent"></child-a>
        <!--父组件中通过监测my-event事件执行一个方法,然后取到子组件中传递过来的值-->
      </div>
    </template>
    <script>
      import ChildA from './components/child.vue'
      export default {
        components: {
          ChildA
        },
        methods: {
          getMyEvent(msg){  // msg是个形参value,实质是接收的子组件传来数据的参数
              console.log('接收的数据--------->'+msg)//接收的数据--------->我是子组件中的数据
          }
        }
      }
    </script>

    二 父传子

    父组件可以使用 props 把数据传给子组件。
    子组件通过props拿到父组件传来的数据。

    父组件

    <template>
      <div id="app">
          <div class="transac-del">
                    <div>
                        <span class="sub_title">交易详情</span>
                    </div>
                    <p>
     // v-if的原因是调接口回来数据是个异步操作,因此给个条件判断,数据不为null的时候才传数据给子组件,以免数据一开始拿到的是空对象
                        <transacDet v-if="deiMap" :DeiMap = 'deiMap' />    // 子组件,并且在数据模型中定义deiMap:null
                    </p>
          </div>
      </div>
    </template>

    子组件

    props: {
         DeiMap:{
             type:Object,
             required: true
         }  
      },
     mounted () {
     // 子组件通过props拿到父组件传来的数据,是个对象,直接this.DeiMap可以使用数据
         console.log('obj==',this.DeiMap)  
      },

    prop的单向数据流

    vue官方:
    所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。

    额外的,每次父级组件发生变更时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

    如下

    可以这样理解
    父传子 prop是单向数据流
    
    如果在子组件中已经接受了值,这时在子组件内直接再次改变这个值,会出现问题,vue不允许这样操作,vue规定了props是单向数据流传值
    
    解决方法
    在data中定义一个第三方的变量接收数据(即克隆数据),这个第三方变量即可更改
    同时,在mounted阶段赋值给这个变量
     

    三 $refs的使用

    $refs作用1   =>  在DOM元素上使用$refs可以迅速进行dom定位
    
    $refs作用2   =>  在组件上使用ref属性,可以通过$refs实现对子组件操作
    即$refs是父组件调用子组件的方法,可以传递数据
    
    首先给子组件做标记。demo :<firstchild ref="one"></firstchild>
    然后在父组件中,通过this.$refs.one就可以访问了这个自组件了,包括访问自组件的data里面的数据,调用它的函数
    
    注意1
    ref 被用来给元素或子组件注册引用信息。引用信息将会注册在父组件的 $refs 对象上。如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素; 如果用在子组件上,引用就指向组件实例
    当 v-for 用于元素或组件的时候,引用信息将是包含 DOM 节点或组件实例的数组
    
    注意2
    $refs不能在created生命周期中使用 因为在组件创建时候 该ref还没有绑定元素
    它是非响应的,所以应该避免在模板或计算属性中使用 $refs ,它仅仅是一个直接操作子组件的应急方案
    当使用v-for的元素或组件,引用信息$refs将是包含DOM节点的或组件实例的数组,类似$children的使用

    父组件

    <template>
      <div id="app">
        <child-a ref="child"></child-a>
        <!--用ref给子组件起个名字-->
        <button @click="getMyEvent">点击父组件</button>
      </div>
    </template>
    <script>
      import ChildA from './components/child.vue'
      export default {
        components: {
          ChildA
        },
        data() {
          return {
            msg: "我是父组件中的数据"
          }
        },
        methods: {
          getMyEvent(){
              this.$refs.child.emitEvent(this.msg);
              //调用子组件的方法,child是上边ref起的名字,emitEvent是子组件的方法。
          }
        }
      }
    </script>

    子组件

    <template>
      <button>点击我</button>
    </template>
    <script>
      export default {
        methods: {
          emitEvent(msg){
            console.log('接收的数据--------->'+msg)//接收的数据--------->我是父组件中的数据
          }
        }
      }
    </script>

    四 $on的使用

    vue中使用 $emit(eventName) 触发事件,使用 $on(eventName) 监听事件

      $emit(eventName)  触发当前实例上的事件,附加参数都会传给监听器回调。

      $on(eventName) 监听当前实例上的自定义事件。事件可以由 vm.$emit 触发。回调函数会接收所有传入事件触发函数的额外参数。

    e.g1 本页面单个事件
    <template>
      <section>
        <h1>left</h1>
        <el-button type="primary" @click="isClick">点击</el-button>
      </section>
    </template>
    
    <script>
      export default {
        methods: {
          isClick() {
            this.$emit('isLeft', '点击事件!');
          }
        },
        mounted() {
          this.$on('isLeft', (val) => {
            console.log(val);
          });
        }
      }
    </script>

    以上代码,是通过按钮的点击事件,然后this.$emit传递事件,然后this.$on捕获本页面的事件

    e.g2 本页面多个事件
    <template>
      <section>
        <h1>left</h1>
        <el-button type="primary" @click="isClick">点击</el-button>
        <el-button type="primary" @click="isClickOther">点击</el-button>
      </section>
    </template>
    
    <script>
      export default {
        methods: {
          isClick() {
            this.$emit('isLeft', '点击事件!');
          },
          isClickOther() {
            this.$emit('isRight', ['点击1', '点击2']);
          }
        },
        mounted() {
          this.$on('isLeft', (val) => {
            console.log(val);
          });
          this.$on('isRight', (...val) => {
            console.log(val);
          });
          this.$on(['isLeft', 'isRight'], () => {
            console.log(666);
          });
        }
      }
    </script>

    以上例子,是本页面的两个点击事件,可以同时监听两个事件,也可以同时传多个参数

    e.g3  非父子组件传值(通过bus传值)

    子组件1

    <template>
      <section>
        <h1>left</h1>
        <el-button type="primary" @click="isClick">点击</el-button>
      </section>
    </template>
    
    <script>
      import eventBus from '~/utils/eventBus';
      export default {
        methods: {
          isClick() {
            eventBus.$emit('isLeft', '点击事件!');
          }
        }
      }
    </script>

    子组件2

    <template>
      <section>
        <h1>right</h1>
        {{ name }}
      </section>
    </template>
    
    <script>
      import eventBus from '~/utils/eventBus';
      export default {
        data() {
          return {
            name: 'right默认值'
          };
        },
        mounted() {
          eventBus.$on('isLeft', (info) => {
            this.name = info ;
          });
        }
      }
    </script>

    父组件

    <template>
      <section>
        <el-row>
          <el-col :span="12">
            <left/>
          </el-col>
          <el-col :span="12">
            <right />
          </el-col>
        </el-row>
      </section>
    </template>
    
    <script>
      import left from '~/components/left'
      import right from '~/components/right'
      export default {
        components: {
          left,
          right
        }
      }
    </script>

    以上例子就是 left组件传值给bus,然后right组件监听bus的isLest事件,当left组件触发事件的时候,right组件就会触发方法,替换页面的值

     总结

    1.使用$emit传递事件

    2.使用$on监听事件

    3.可以本页面使用,也可以父子组件使用,也可以非关联组件使用

    五 $parent

    vue 里 this.$parent 作用
    $parent在子组件中调用父组件的方法或获得其数据
    this.$parent 可以访问到父组件上所有的 data(){ 里的数据信息和生命周期方法,methods里的方法 }
    
    如 this.$parent.List = []; 表示访问到父组件中data的数据list数组
    
    区分
    1、ref为子组件指定一个索引名称,通过索引来操作子组件;
    2、this.$parent 可以直接访问该组件的父实例或组件;
    3、父组件也可以通过this.$children 访问它所有的子组件,
    $parent和$children 可以递归向上或向下无线访问, 直到根实例或最内层的组件。

    六 $children

    他返回的是一个组件集合,如果你能清楚的知道子组件的顺序,你也可以使用下标来操作;

    for(let i=0;i<this.$children.length;i++){
              console.log(this.$children[i].children_data);
              this.$children[i].children_fun();
            }

    七 parent和children的案例

    父组件index.vue

    <template>
    <div>
      <testVue ref="childVue"></testVue>  <br/><br/>
      <testVue2></testVue2> <br/><br/>
      <button @click="clickChild1">点击访问子组件</button> <br/><br/>
      <button @click="clickChild2">点击访问子组件2</button>
    </div>
    </template>
    <script>
    import testVue from './testVue'
    import testVue2 from './testVue2'
    export default {
      data(){
        return {
          total: 0
        }
      },
      methods: {
        clickChild1(){
          console.log(this.$refs.childVue.counter);
        },
        clickChild2(){
           console.log(this.$children[1].testval);
        }
      },
      components: {
        testVue,
        testVue2  
      }
    }
    </script>

    子组件1

    <template>
    <div>
      <button @click="parentClick">点击访问父组件</button>
    </div>
    </template>
    <script>
    export default {
      data(){
        return {
          counter: 0
        }
      },
      methods: {
        parentClick(){
           console.log(this.$parent.total);
        }
      }
    }
    </script>

    子组件2

    <template>
    <div>
    </div>
    </template>
    <script>
    export default {
      data(){
        return {
          testval: '2222'
        }
      }
    }
    </script>
     
  • 相关阅读:
    Java深度历险(四)——Java垃圾回收机制与引用类型
    Java深度历险(三)——Java线程​:基本概念、可见性与同步
    Java深度历险(一)——Java字节代码的操纵(转)
    SVN问题:Cleanup failed to process the following paths: xxxxxx
    解决 ORA-12154: TNS:could not resolve service name
    Linq 实现普通sql中 where in 的功能
    C# 操作电脑 关机 重启 注销 休止 休眠
    使用C#代码追加和提交文件到SVN服务器
    access 2007 vba (亖)
    access 2007 vba 开发中学到的知识(三)
  • 原文地址:https://www.cnblogs.com/huoshengmiao/p/15236699.html
Copyright © 2020-2023  润新知