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>
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM