vue組件傳值&vuex

vue技術分享

目錄

一、vue組件之間的通信

1. 父組件傳值給子組件 </br>
<!--父組件代碼-->
<template>
  <div>
    <div  class="box">
      <h1>父組件</h1>
      <input type="text" v-model="msg"> <br>
      <div>
        <p>測試參數(shù):{{msg}}</p>
      </div>
    </div>
    <div class="box">
      <Demo1Child :info="msg"></Demo1Child>
    </div>   
  </div>
</template>

<script>
import Demo1Child from '@/components/DemoChild'
export default {
  name: 'HelloWorld',
  components:{
    Demo1Child
  },
  data () {
    return {
      msg: ''
    }
  }
}
</script>
<!--子組件代碼-->
<template>
  <div>
    <h1>子組件</h1>
    <input type="text" v-model="info"> <br>
    <p>{{info}}</p>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {  
    info: {  
      type: String,  
      default: function () {  
        return ''  
      }  
    }  
  }
}
</script>

父組件使用屬性綁定的方式給子組件綁定需要給子組件傳遞的數(shù)據,子組件使用props接收。(子組件直接使用 input, v-model綁定props此處有坑) ==demochild1==

2. 子組件給父組件傳遞參數(shù)
<!--父組件代碼-->
<template>
  <div>
    <div  class="box">
      <h1>父組件</h1>
      <div>
        <p>子組件傳遞上來的參數(shù):{{childrenData}}</p>
      </div>
    </div>
    <div class="box">
      <DemoChild2 :info="msg" v-on:listenChildEvent="showChildData"></DemoChild2>
    </div>
  </div>
</template>

<script>
import DemoChild2 from '@/components/DemoChild2';
export default {
  name: 'HelloWorld',
  components:{
    DemoChild1,
    DemoChild2
  },
  data () {
    return {
      msg: '',
      childrenData:''
    }
  },
  methods:{
    showChildData(data){
      this.childrenData = data;
    }
  }
}
</script>
<!--子組件代碼-->
<template>
  <div>
    <h1>子組件</h1>
    <input type="text" v-model="childData" @change="emitFather()"> <br>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data(){
    return{
      childData:''
    }
  },
  methods:{
    emitFather(){
      this.$emit('listenChildEvent',this.childData);
    }
  }
}
</script>

子組件中需要以某種方式例如點擊事件的方法來觸發(fā)一個自定義事件; </br>
將需要傳的值作為$emit的第二個參數(shù),該值將作為實參傳給響應自定義事件的方法;</br>
在父組件中注冊子組件并在子組件標簽上使用 v-on 對自定義事件的監(jiān)聽 ==DemoChild2==

3. 父子組件數(shù)據的雙向通信

==prop 是單向綁定的==:當父組件的屬性變化時,將傳導給子組件,但是不會反過來。這是為了防止子組件無意修改了父組件的狀態(tài)——這會讓應用的數(shù)據流難以理解。
另外,每次父組件更新時,子組件的所有 prop 都會更新為最新值。這意味著你不應該在子組件內部改變 prop。如果你這么做了,Vue 會在控制臺給出警告 ==DemoChild3==

<!--父組件代碼-->
<template>
  <div>
    <div  class="box">
      <h1>父組件3</h1>
      <div>
        <input type="text" v-model="msg">
        <p>{{msg}}</p>
      </div>
    </div>
    <div class="box">
      <DemoChild3 :msg.sync="msg"></DemoChild3>
    </div>
  </div>
</template>

<script>
import DemoChild3 from '@/components/DemoChild3';
export default {
  name: 'HelloWorld',
  components:{
    DemoChild1,
    DemoChild2,
    DemoChild3
  },
  data () {
    return {
      msg: '',
      childrenData:''
    }
  },
  methods:{
    showChildData(data){
      this.childrenData = data;
    }
  }
}
<!--子組件代碼-->
<template>
  <div>
    <h1>子組件3</h1>
    <input type="text" v-model="childData"> <br>
    <p>{{msg}}</p>
    <input type="button" value="點我加一下" @click="emitFather()">
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data(){
    return{
      childData:''
    }
  },
  props: {  
    msg: {  
      type: String,  
      default: function () {  
        return ''  
      }  
    }  
  },
  methods:{
    emitFather(){
      this.$emit('update:msg',this.childData);
    }
  }
}
</script>
4. 非父子組件之間的通信

實現(xiàn)非父子組件間的通信,可以通過創(chuàng)建一個vue實例Bus作為媒介,要相互通信的兄弟組件之中,都引入Bus,之后通過分別調用Bus事件觸發(fā)和監(jiān)聽來實現(xiàn)組件之間的通信和參數(shù)傳遞。

<!--bus.js-->
import Vue from 'vue';
export default new Vue;
<!--組件一-->
<template>
  <div>
    <h1>組件一</h1>
    <input type="text" v-model="message"> 
    <input type="button" value="確認傳遞參數(shù)" @click="bus()">
  </div>
</template>
<script>
import Bus from './bus'
export default {
  data () {
    return {
      message:'111',
    };
  },
  methods:{
    bus () {
      Bus.$emit('msg',this.message);
    }
  }
}
<!--組件二-->
<template>
  <div>
    <h1>組件二</h1>
    <p>{{message}}</p>
  </div>
</template>
<script>
import Bus from './bus'
export default {
  data () {
    return {
      message:''
    };
  },
  mounted() {
  let self = this;
    Bus.$on('msg', (e) => {
      self.message = e
     console.log(`傳來的數(shù)據是:${e}`);
    })
  }  
}

二、vuex狀態(tài)管理

  • 多個視圖依賴于同一狀態(tài)。
  • 來自不同視圖的行為需要變更同一狀態(tài)。

對于問題一,傳參的方法對于多層嵌套的組件將會非常繁瑣,并且對于兄弟組件間的狀態(tài)傳遞無能為力。
對于問題二,我們經常會采用父子組件直接引用或者通過事件來變更和同步狀態(tài)的多份拷貝。以上的這些模式非常脆弱,通常會導致無法維護的代碼。


vuex是一個專門為vue.js設計的集中式狀態(tài)管理架構。狀態(tài)?我把它理解為在data中的屬性需要共享給其他vue組件使用的部分,就叫做狀態(tài)。簡單的說就是data中需要共用的屬性。比如:我們有幾個頁面要顯示用戶名稱和用戶等級,或者顯示用戶的地理位置。如果我們不把這些屬性設置為狀態(tài),那每個頁面遇到后,都會到服務器進行查找計算,返回后再顯示。

  • 首先安裝vuex插件 npm install vuex --save
  1. State
  2. Mutation
  3. Getter
  4. Action
  5. Module

State:這個就是我們說的訪問狀態(tài)對象,它就單頁應用中的共享值。怎么將狀態(tài)對象賦值給內部對象,也就是把stroe.js中的值,賦值給模板里data中的值。一般有三種方式。

1.通過computed的計算屬性直接賦值

computed屬性可以在輸出前,對data中的值進行改變,我們就利用這種特性把store.js中的state值賦值給我們模板中的data值。

computed:{
    test(){
        return this.$store.state.count;   //store.state.count
    }
},
store
2.mapState 輔助函數(shù)——通過對象賦值

需要在組件中引入==import {mapState} from 'vuex';==

computed:mapState({
    test:function(state){
      return state.count;
    }
}),
3.mapState 輔助函數(shù)——通過數(shù)組賦值
computed:mapState(["count"])

Mutation:更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation。要想更改store中state的值,只能通過mutation。

1.Vuex提供了==commit==方法來修改狀態(tài)

組件中這樣使用commit

<button @click="$store.commit('add')">+</button>
<button @click="$store.commit('reduce')">-</button>

store.js中這樣定義mutation

const mutations={
  add(state){
      state.count++;
  },
  reduce(state){
      state.count--;
  }
}
2.提交載荷(Payload)——傳值

組件中這樣定義傳值

<button @click="$store.commit('add','this')">+</button>

store.js中這樣定義mutation中的add方法

const mutations={
  add(state,test){
    state.count = test;
  },
  reduce(state){
      state.count--;
  }
}
3.模板獲取mutation中的方法

需要在組件中引入 ==import {mapMutations} from 'vuex';==

組件中js代碼可以這樣寫

methods:{
    ...mapMutations(['add','reduce']),
},

組件中的html代碼可以這樣寫

<button @click="add('this')">+</button>

Getters:getters從表面是獲得的意思,可以把他看作在獲取數(shù)據之前進行的一種再編輯,相當于對數(shù)據的一個過濾和加工

在store.js中這樣寫

const getters = {
    count:function(state){
        return state.count +=100;
    }
}

在組件中這樣寫

computed:{
    // count(){
    //     return this.$store.getters.count;
    // },
    ...mapGetters(["count"])
  }

Actions:actions和的Mutations功能基本一樣,不同點是,actions是異步的改變state狀態(tài),而Mutations是同步改變狀態(tài)

在store.js中這樣寫

const actions ={
    addAction(doAnything){
        // doAnything.commit('add',5)
        setTimeout(function(){
            doAnything.commit('add',5);
        },3000)
        console.log('我比add提前執(zhí)行');
    },
    reduceAction({commit}){
        commit('reduce')
    }
}

在組件中這樣寫

methods:{
    ...mapMutations([  
      'add','reduce'
    ]),
    ...mapActions(['addAction','reduceAction'])
}

三、vue中數(shù)據監(jiān)聽watch的使用

watch首先是一個對象,是對象就有鍵名(你要監(jiān)聽的對象數(shù)據),鍵值(可以是函數(shù),函數(shù)名,對象),鍵值如果是對象選項有三個

  • 第一個handler:其值是一個回調函數(shù)。即監(jiān)聽到變化時應該執(zhí)行的函數(shù)(不能使用箭頭函數(shù))。
  • 第二個是deep:其值是true或false;確認是否深入監(jiān)聽。(一般監(jiān)聽時是不能監(jiān)聽到對象屬性值的變化的,數(shù)組的值變化可以聽到。)
  • 第三個是immediate:其值是true或false;確認是否以當前的初始值執(zhí)行handler的函數(shù)。
<template>
  <div>
        <p>今天掙了{{money}}元</p>
        <p>晚餐可以吃個{{food}}</p>
        <p>
            <button @click="add">加班</button>
            <button @click="reduce">偷懶</button>
        </p>
        <input type="text" v-model="arr[0]"> <br>
        <input type="text" v-model="obj.name">
  </div>
</template>

<script>
var foods=['菜夾饃','肉夾饃','牛肉面','肯德基全家桶','六菜一湯'];
export default {
  data () {
    return {
        food:'菜夾饃',
        money:5,
        arr:[1,2,3,4],
        obj:{
            name:'李四',
            age:18,
            sex:'女'
        }
    };
  },
  methods:{
    add:function(){
        this.money+=5;
    },
    reduce:function(){
        this.money-=5;
    }
  },
  watch:{
    money:function(newVal,oldVal){
        if(newVal<5){
            this.food = '土'
        }else if(newVal==5){
            this.food=foods[0];
        }else if(newVal==10)
        {
            this.food=foods[1];
        }else if(newVal==15)
        {
            this.food=foods[2];
        }else if(newVal==20)
        {
            this.food=foods[3];
        }else{
            this.food=foods[4];
        }
    },
    arr:{
        handler(curVal,oldVal){

       console.log(curVal,oldVal)
     },
//      deep:true
    },
    obj:{
        handler(newVal,oldVal){
            console.log(newVal,oldVal);
        },
        deep:true
    }
  }
}

</script>

注意項:在使用數(shù)據監(jiān)聽的同時要使用原聲js獲取DOM節(jié)點,一定要加上非空判斷,不然代碼容易報錯

watch: {
    'name': function (newVal, oldVal) {
      this.variable_arr = []
      this.temp = []
      if (newVal.content && newVal.content !== '') {
        let str = newVal.content.replace('%storeName%', `(${this.currentStore.store_name})`)
        let temp = []
        this.temp = str.split('%')
        this.temp.forEach((v, index) => {
          if ((index + 1) % 2 !== 0) {
            temp.push(v)
          }
        })
        this.views = temp.join('')
        this.count = Math.ceil((this.views.length + this.identification.length) / 70) * this.phone_list.length
      }
      if (document.getElementsByClassName('smsref') && document.getElementsByClassName('smsref')[0]) {
        document.getElementById('refForm').reset()
      }
    },
},

四、vue里ref ($refs)用法

ref 有三種用法 https://www.cnblogs.com/goloving/p/9404099.html

  1. ref 加在普通的元素上,用this.ref.name 獲取到的是dom元素
  2. ref 加在子組件上,用this.ref.name 獲取到的是組件實例,==可以使用組件的所有方法。==
  3. 如何利用 v-for 和 ref 獲取一組數(shù)組或者dom 節(jié)點
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容