Vue—組件傳值及vuex的使用

1、父子組件之間的傳值

1.父組件向子組件傳值:

  1. 子組件在props中建立一個屬性,用以接收父組件傳來的值
  2. 父組件中註冊子組件
  3. 在子組件標籤中添加子組件props中建立的屬性
  4. 把須要傳給子組件的值賦給該屬性

在子組件中建立props,而後建立一個名爲 ‘img-src’ 的數據名html

//子組件BigImg.vue
<template>
  <!-- 過渡動畫 -->
  <transition name="fade">
    <div class="img-view" @click="bigImg">
      <!-- 遮罩層 -->
      <div class="img-layer"></div>
      <div class="img">
        <img :src="img-src">
      </div>
    </div>
  </transition>
</template>
<script>
  export default {
    props: ['img-src'],
    methods: {
     
    }
  }
</script>

在父組件中註冊子組件,並在template中加入子組件標籤,標籤中添加img-src屬性並賦值vue

<template>
  <div class="">
    <v-head></v-head>
    <big-img v-if="showImg" :img-src="imgSrc"></big-img>
</template>

<script>
  import vHead from '../components/Header'
  import BigImg from '../components/BigImg'
  export default {
    name: 'Home',
    components: {
      vHead,BigImg
    },
    data() {
      return {
        showImg:false,
        imgSrc: ''
      }
    }
</script>

2.子組件向父組件傳值

  • 子組件中須要以某種方式例如點擊事件的方法來觸發一個自定義事件
  • 將須要傳的值做爲$emit的第二個參數,該值將做爲實參傳給響應自定義事件的方法
  • 在父組件中註冊子組件並在子組件標籤上綁定對自定義事件的監聽

在子組件中建立一個按鈕,給按鈕綁定一個點擊事件ios

在響應該點擊事件的函數中使用$emit來觸發一個自定義事件,並傳遞一個參數vuex

// 發送事件
this.$emit('clickit')

在父組件中的子標籤中監聽該自定義事件並添加一個響應該事件的處理方法npm

<big-img @clickit="viewImg"></big-img>

clickImg(e) {
    this.showImg = true;
    // 獲取當前圖片地址
    console.log(e);
    this.imgSrc = e.currentTarget.src;
}
在通訊中,不管是子組件向父組件傳值仍是父組件向子組件傳值,他們都有一個共同點就是有中間介質,子向父的介質是自定義事件,父向子的介質是props中的屬性。抓準這兩點對於父子通訊就好理解了

http://www.javashuo.com/article/p-xhqyxikg-ee.htmlaxios

2、經過路由帶參數傳值

兩個組件 A和B,A組件經過query把orderId傳遞給B組件(觸發事件能夠是點擊事件、鉤子函數等)api

this.$router.push({ path: '/conponentsB', query: { orderId: 123 } }) // 跳轉到B

在B組件中獲取A組件傳遞過來的參數、緩存

this.$route.query.orderId

3、安裝、使用 vuex

 安裝vuexapp

npm install vuex --save

1.在src目錄下新建store文件夾並在該文件夾下新建index.js文件。 在 store/index.js寫入:異步

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  strict:true,  // 開啓嚴格模式  確保state 中的數據只能 mutations 修改
  state:{
    count:0
  }
})

export default store;

在main.js中引入:

import store from './store'

new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

此時能夠在組件中使用 this.$store.state.count 獲取store中state的值。如:

// 在組件的computed中使用
  computed:{
     count(){
      return this.$store.state.count;
     }
  }
<template>
  <div class="hello">
    <h2>{{count}}</h2>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  computed:{
     count(){
       return this.$store.state.count;
     }
  }
}
</script>

不少時候我們要對state裏的值進行操做,在vuex提供了一個方法mutations

mutations用法(使用mutations能夠修改state的值)

在store/index.js中寫入:

//
...
  state:{
    count:0
  },
  mutations:{ // 更改數據的方法
    add(state){
      state.count++
    },
    //提交載荷用法
//     add(state,n){  
//      state.count += n
//    },
    sub(state){
      state.count--
    }
  }
...
//

在組件中使用mutations中對應的方法

<template>
  <div class="hello">
    <button @click="add">+</button>
    <h2>{{count}}</h2>
    <button @click="sub">-</button>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  computed:{
     count(){
       return this.$store.state.count;
     }
  },
    methods:{
    add(){
      this.$store.commit('add');
    },
    
    //提交載荷用法
   // add(){  
   //    this.$store.commit('add',10);
   // },
   
   //對象風格的提交方式
   //   store.commit({
   //     type: 'add',
   //     n: 10
   //     })
   
    sub(){
      this.$store.commit('sub');
    }
  }
}
</script>

此時就能夠對count進行修改了。

補充1:mutation接收單個參數和多個參數

利用$store.commit 裏面 寫參數至關於 mutation的函數名字

在組件裏面:
    第一種方式: this.$store.commit("addIncrement",{name:'stark',age:18,n:5})
    第二種方式:
    this.$store.commit({
        type:"addIncrement",
        n:5,
        age:18,
        name:'stark.wang'
    })

在vuex裏面接收:接收第二個參數至關於前面傳過來的參數,若是多個這個就是對象,若是是一個參數,這個第二個參數payload就是前面的參數,例如

let store = new Vuex.Store({
    state: {
        num: 100
    },
    mutations: {
        // 任什麼時候候改變state的狀態都經過提交 mutation 來改變
        // 裏面能夠定義多個函數,當觸發這個函數就會改變state狀態
        addIncrement(state, stark) {
            console.log(stark);
            // 接收一個state做爲參數, 至關於上面的state
             // 在vuex裏面接收:接收第二個參數至關於前面傳過來的參數,若是多個這個就是對象,若是是一個參數,這個第二個參數payload就是前面的參數。
            // mutations設計原則是同步的
            //state.num += stark;
            state.num += stark.n;
        

        },
        minIncrement(state) {
            state.num -= 5;
        }
    }

})

補充2:遇到在組件input中直接修改state中數據的問題

在組件中寫入

<div class="form-control amis-control">
  <input name="name" placeholder="" type="text" autocomplete="off" :value="activeFormData.title" @input="updataMessage($event,'t1.title')">
</div>

<script>
...
computed:{
  activeFormData(){
    return this.$store.state.formData.t1
  }
},
methods:{
  updataMessage(e,dataposition){
    let newposition = dataposition.split('.);
    this.$store.commit('updataMessage',{newval:e.target.value,curposition:newposition})
  }
}
</script>

在store.js中寫入

mutations:{
  ...
  updataMessage(state, stark) {
      if (stark.curposition.length == 2) {
        state.formData[stark.curposition[0]][stark.curposition[1]] = stark.newval
      } else if (stark.curposition.length == 3) {
        state.formData[stark.curposition[0]][stark.curposition[1]][stark.curposition[2]] = stark.newval
      }

    },  
}

 

當你想異步操做的時候,因爲mutation必須是同步的這一點,此時不能採用mutation對state 進行修改。action派上用場了,action就是一個函數集合,在裏面怎麼操做均可以,只要最後觸發mutation 就能夠了。

註解mutation不能異步操做的緣由:

 mutations: {
   add (state) {
     api.callAsyncMethod(() => {
    state.count++
   })
  }
}
如今想象,咱們正在 debug 一個 app 而且觀察 devtool 中的 mutation 日誌。每一條 mutation 被記錄,devtools 都須要捕捉到前一狀態和後一狀態的快照。然而,在上面的例子中 mutation 中的異步函數中的回調讓這不可能完成:由於當 mutation 觸發的時候,回調函數尚未被調用,devtools 不知道何時回調函數實際上被調用——實質上任何在回調函數中進行的狀態的改變都是不可追蹤的。
 

Action 用法

在store/index.js中寫入

mutations:{ // 更改數據的方法
    add(state){
      state.count++
    },
    sub(state){
      state.count--
    }
  },
++++
  actions:{
    addAction(context){  // context 與 store 實例具備相同方法和屬性(但不是store 實例)
      setTimeout(()=>{
        context.commit('add');
      },1000)
    }
  }
++++

組件中使用getters裏對應的方法:

<template>
  <div class="hello">
    <button @click="add">+</button>
    ++++
    <button @click="add_action">action +</button>
    ++++
    <h2>{{count}}</h2>
    <button @click="sub">-</button>
    <div>
      test: {{doneTodos[0].text}} <br>
      length: {{doneTodosLength}}
    </div>
  </div>
</template>
export default {
  methods:{
    add(){
      this.$store.commit('add');
      // console.log(this);
    },
    sub(){
      this.$store.commit('sub');
    },
    ++++
    add_action(){
      this.$store.dispatch('addAction');
    }
    ++++
  }
}

實際異步操做

組件methods中:

 

 

 

 在store/index.js中引入axios :

import axios from 'axios'

 

 

 看到這裏有沒有想過當咱們使用state中某一個數據時,咱們只想用該數據中符合條件的數據。好比:

state:{
    count:0,
    todos: [
      { id: 1, text: 'text1--true', done: true },
      { id: 2, text: 'text2--false', done: false }
    ]
  }
此時咱們只想獲取state.todos中done爲true的數據時咱們應該怎麼獲取?
可能會有如下兩種方案:
1.每一個在組件中首先獲取todos,而後使用filter方法過濾;
2.寫一個公共函數在每一個組件中調用如下;
若是用到todos中done爲true的組件不少,這兩種方法都是很不理想的。Vuex爲此爲咱們引入了一個方法Getter。
 

Getter 用法

官方解釋:Vuex 容許咱們在 store 中定義「getter」(能夠認爲是 store 的計算屬性)。就像計算屬性同樣,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變纔會被從新計算。

在store\index.js寫入:
mutations:{ // 更改數據的方法
    add(state){
      state.count++
    },
    sub(state){
      state.count--
    }
  },
  +++
  getters:{  // 用法相似組件中的 computed, 能夠認爲是store的計算屬性
    doneTodos:state => { // Getter 接受 state 做爲其第一個參數:
      return state.todos.filter(todo => todo.done)  // -> [{ id: 1, text: 'text1--true', done: true }]
    },
    // Getter 也能夠接受其餘 getter 做爲第二個參數
    doneTodosLength:(state,getters) => {
      return getters.doneTodos.length // -> 1
    },
  +++
  }

在組件中使用getter對應的方法:

<template>
  <div class="hello">

    <button @click="add">+</button>
    <h2>{{count}}</h2>
    <button @click="sub">-</button>

+++
    <div>
      test: {{doneTodos[0].text}} <br>
      length: {{doneTodosLength}}
    </div>
+++    
  </div>
</template>
<script>
export default {
  //...
    computed:{
    +++
        doneTodos(){
          return this.$store.getters.doneTodos // -> [{ id: 1, text: 'text1--true', done: true }]
        },
        doneTodosLength(){
          return this.$store.getters.doneTodosLength // -> 1
        }
    +++
  }
}
</script>

做者:朴樹-連接:https://juejin.im/post/5bf7c4375188254b9d0935c9來源:掘金著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。

相關文章
相關標籤/搜索