欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue組件間通信的實現(xiàn)方法講解

 更新時間:2023年01月09日 09:21:38   作者:酷爾。  
組件是vue.js最強大的功能之一,而組件實例的作用域是相互獨立的,這就意味著不同組件之間的數(shù)據(jù)無法相互進(jìn)行直接的引用,所以組件間的相互通信是非常重要的

前言

前面介紹過幾種可以實現(xiàn)組件間通信的方式props、ref、自定義事件綁定、全局事件總線、插槽…,這些要么就是實現(xiàn)組件間通信只能在特定條件下使用,要么就是實現(xiàn)起來太復(fù)雜,今天介紹到的vuex是Vue中一款強大的插件,使用vuex后可以實現(xiàn)任意組件間通信,并且支持模塊化管理。接下來將會圍繞一個計數(shù)案例進(jìn)行展開,逐步引入vuex如何使用。

核心代碼:

<template>
  <div>
      <h2>目前的數(shù)值結(jié)果是:{{n}}</h2>
      <div class="container1">
          <select v-model.number="step">
              <option value="1">1</option>
              <option value="2">2</option>
              <option value="3">3</option>
          </select>
          <button @click="addNum">增加</button>
          <button @click="subNum">減少</button>
          <button @click="oddNum">偶數(shù)再加</button>
          <button @click="longTimeAdd">延遲增加</button>
      </div>
  </div>
</template>
<script>
export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Counts",
    data(){
        return {
            n:0,
            step:1
        }
    },
    methods:{
        addNum(){
            this.n+=this.step
        },
        subNum(){
            this.n-=this.step
        },
        oddNum(){
            if (this.n%2==0){
                this.n+=this.step
            }
        },
        longTimeAdd(){
            setTimeout(() => {
                this.n+=this.step
            }, 1000);
        }
    }
}
</script>
<style>
.container1>*{
    margin-left: 10px; 
}
</style>

一、vuex是什么

簡單點說:是一個數(shù)據(jù)倉庫,用于數(shù)據(jù)存儲,數(shù)據(jù)共享,可以進(jìn)行數(shù)據(jù)存放與獲取,并全程監(jiān)視數(shù)據(jù)的動向

使用官方語言入下:

Vuex 是一個專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式 + 庫。它采用集中式存儲管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化。

這個狀態(tài)自管理應(yīng)用包含以下幾個部分:

  • 狀態(tài),驅(qū)動應(yīng)用的數(shù)據(jù)源;
  • 視圖,以聲明方式將狀態(tài)映射到視圖;
  • 操作,響應(yīng)在視圖上的用戶輸入導(dǎo)致的狀態(tài)變化。

但是,當(dāng)我們的應(yīng)用遇到多個組件共享狀態(tài)時,單向數(shù)據(jù)流的簡潔性很容易被破壞:

多個視圖依賴于同一狀態(tài)。

來自不同視圖的行為需要變更同一狀態(tài)。

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

因此,我們?yōu)槭裁床话呀M件的共享狀態(tài)抽取出來,以一個全局單例模式管理呢?在這種模式下,我們的組件樹構(gòu)成了一個巨大的“視圖”,不管在樹的哪個位置,任何組件都能獲取狀態(tài)或者觸發(fā)行為!

通過定義和隔離狀態(tài)管理中的各種概念并通過強制規(guī)則維持視圖和狀態(tài)間的獨立性,我們的代碼將會變得更結(jié)構(gòu)化且易維護。

這就是 Vuex 背后的基本思想,借鑒了 Flux、Redux 和 The Elm Architecture。與其他模式不同的是,Vuex 是專門為 Vue.js 設(shè)計的狀態(tài)管理庫,以利用 Vue.js 的細(xì)粒度數(shù)據(jù)響應(yīng)機制來進(jìn)行高效的狀態(tài)更新。

vuex適用于大型單頁應(yīng)用的開發(fā),如果是小型的不推薦使用。

其中vuex3適配vue2,vuex4適配vue3。

vue工作原理:

vuex中主要包含三個部分

  • Actions:相當(dāng)于對數(shù)據(jù)的預(yù)處理(可以在這里使用異步加載進(jìn)行數(shù)據(jù)校驗等)
  • Mutations (跟開發(fā)者工具關(guān)系密切)
  • State (存放數(shù)據(jù)的地方,經(jīng)過校驗與變換的數(shù)據(jù)都存放在這里)

vuex中的兩種數(shù)據(jù)操作

  • dispatch:將數(shù)據(jù)交給Actions
  • commit:將數(shù)據(jù)交給Mutations

vuex在項目中使用

大致有兩種(實質(zhì)上一樣):

  • 1.vuex/store.js 創(chuàng)建vuex文件夾,將代碼放進(jìn)store.js中
  • 2.store/index.js 創(chuàng)建store文件夾,將代碼放進(jìn)index.js中

安裝vuex

npm i vuex

二、vuex的使用

繼續(xù)從以下三個模塊與兩個方法講起:

三個模塊:

  • Actions:相當(dāng)于對數(shù)據(jù)的預(yù)處理(可以在這里使用異步加載進(jìn)行數(shù)據(jù)校驗等)
  • Mutations (跟開發(fā)者工具關(guān)系密切)
  • State (存放數(shù)據(jù)的地方,經(jīng)過校驗與變換的數(shù)據(jù)都存放在這里)

兩個方法:

  • dispatch:將數(shù)據(jù)交給Actions
  • commit:將數(shù)據(jù)交給Mutations

如果調(diào)用vuex的dispatch方法會將數(shù)據(jù)提交到Actions中的函數(shù),此時數(shù)據(jù)并不是最終的結(jié)果,在Actions中可以對數(shù)據(jù)進(jìn)行進(jìn)一步加工,然后調(diào)用commit方法提交,在Actions與Mutations中定義的函數(shù)可以獲取到上下文找到state對象中存儲的數(shù)據(jù)。

接下來結(jié)合代碼看一下vuex如何使用(這一段代碼暴露出去一個可以使用的vuex對象):

import Vue from "vue"
import Vuex from "vuex"
Vue.use(Vuex)
const actions={
    odd_Num(comtext,value){
        // 可以通過上下文comtext找到commit方法,dispatch方法
        // 可以找到state對象,并找到其中的屬性
        if (comtext.state.n%2===0){
            comtext.commit("add_Num",value)
        }
    },
    long_Time_Add(comtext,value){
        setTimeout(() => {
            comtext.commit("add_Num",value)
        }, 1000);
    }
}
const mutations={
    add_Num(state,value){
        // 這里的state被稱為上下文,這里可以拿到state中的數(shù)據(jù)
        // console.log(state,value)
        state.n+=value
    },
    sub_Num(state,value){
        // console.log(state,value)
        state.n-=value
    },
}
//數(shù)據(jù)源,源數(shù)據(jù)
const state={
    n:0
}
//創(chuàng)建一個vuex對象
export default new Vuex.Store({
    actions,
    mutations,
    state
})

以下代碼是使用vuex:

main.js

import App from "./App"
//這個便是剛才封裝的vuex對象
import store from "./store"
import Vue from "vue"
new Vue({
    el:"#App",
    store,
    render:h=>h(App)
})

功能性組件:

export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Counts",
    data(){
        return {
            step:1
        }
    },
    computed:{
        n(){
            return this.$store.state.n
        }
    }
    ,
    methods:{
        addNum(){
            this.$store.commit("add_Num",this.step)
        },
        subNum(){
            this.$store.commit("sub_Num",this.step)
        },
        oddNum(){
            this.$store.dispatch("odd_Num",this.step)
        },
        longTimeAdd(){
            this.$store.dispatch("long_Time_Add",this.step)
        }
    }
}

除此之外vuex還有一個重要的模塊供我們使用getters,這里面的方法通常用于獲取定制后的state中的屬性

比如下面一個實例,就是將state中的n擴大10倍后返回了出去。

const getters={
    numBig(state){
        return state.n*10
    }
}

三、四個重要的映射函數(shù)

如果vuex中的函數(shù)較多時,一個一個引入會相當(dāng)麻煩,官方給出了四個映射函數(shù),可以根據(jù)自己的需求將想要的函數(shù)一下引進(jìn)來,分別是:mapState,mapGetters,mapActions,mapMutations。

以下兩種寫法,在使用時效果是一樣的

不使用映射函數(shù):

<script>
export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Counts",
    data(){
        return {
            step:1
        }
    },
    computed:{
        n(){
            return this.$store.state.n
        },
        bigNum(){
            // 以下兩種寫法均可以
            // return this.$store.getters["numBig"]
            return this.$store.getters.numBig
        }
    }
    ,
    methods:{
        addNum(){
            this.$store.commit("add_Num",this.step)
        },
        subNum(){
            this.$store.commit("sub_Num",this.step)
        },
        oddNum(){
            this.$store.dispatch("odd_Num",this.step)
        },
        longTimeAdd(){
            this.$store.dispatch("long_Time_Add",this.step)
        }
    }
}
</script>

使用映射函數(shù):

<script>
import {mapState,mapGetters,mapActions,mapMutations} from "vuex"
export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Counts",
    data(){
        return {
            step:1
        }
    },
    computed:{
        ...mapState(["n"]),
        ...mapGetters({bigNum:"numBig"})
    }
    ,
    methods:{
        // 傳入對象是常規(guī)寫法,當(dāng)對象中的鍵值相等時,可以用傳入列表的方式進(jìn)行傳參
        // 例如上面的mapState(["n"])
        ...mapMutations({addNum:"add_Num",subNum:"sub_Num"}),
        ...mapActions({oddNum:"odd_Num",longTimeAdd:"long_Time_Add"})
    }
}
</script>

四、多組件數(shù)據(jù)共享

經(jīng)過將多個組件使用到的數(shù)據(jù)提取到vuex,可以實現(xiàn)多組件間的數(shù)據(jù)共享,也就是說在a組件修改共享數(shù)據(jù)之后,在b組件可以渲染出數(shù)據(jù)改變后的結(jié)果,同樣b組件中修改a組件也可以渲染。

以下案例一個計數(shù)組件負(fù)責(zé)計數(shù),一個person組件,負(fù)責(zé)將人員列表渲染出來,person組件支持增加用戶,我們要做的就是person組件中進(jìn)行人員添加后,計數(shù)組件感應(yīng)到人數(shù)變動,重新渲染列表,將總?cè)藬?shù)進(jìn)行改變。

vuex插件

import Vue from "vue"
import Vuex from "vuex"
import {nanoid} from "nanoid"
Vue.use(Vuex)
const actions={
    odd_Num(comtext,value){
        // 可以通過上下文comtext找到commit方法,dispatch方法
        // 可以找到state對象,并找到其中的屬性
        if (comtext.state.n%2===0){
            comtext.commit("add_Num",value)
        }
    },
    long_Time_Add(comtext,value){
        setTimeout(() => {
            comtext.commit("add_Num",value)
        }, 1000);
    },
    add_Person(context,value){
        var someone={id:nanoid(),name:value}
        context.commit("add_Person",someone)
    }
}
const mutations={
    add_Num(state,value){
        // 這里的state被稱為上下文,這里可以拿到state中的數(shù)據(jù)
        // console.log(state,value)
        state.n+=value
    },
    sub_Num(state,value){
        // console.log(state,value)
        state.n-=value
    },
    add_Person(state,value){
        state.personList.unshift(value)
    }
}
const state={
    n:0,
    personList:[
        {
            id:"0001",
            name:"張三"
        }
    ]
}
const getters={
    numBig(state){
        return state.n*10
    },
    personNum(state){
        return state.personList.length
        // console.log("index"+state.personList.length)
    }
}
export default new Vuex.Store({
    actions,
    mutations,
    state,
    getters
})

計數(shù)組件

<template>
  <div>
      <h2>目前的數(shù)值結(jié)果是:{{n}}</h2>
      <h2>放大后的數(shù)值結(jié)果是:{{bigNum}}</h2>
      <div class="container1">
          <select v-model.number="step">
              <option value="1">1</option>
              <option value="2">2</option>
              <option value="3">3</option>
          </select>
          <button @click="addNum(step)">增加</button>
          <button @click="subNum(step)">減少</button>
          <button @click="oddNum(step)">偶數(shù)再加</button>
          <button @click="longTimeAdd(step)">延遲增加</button>
      </div>
      <h2>當(dāng)前的總?cè)藬?shù)為{{personNum}}</h2>
  </div>
</template>
<script>
import {mapState,mapGetters,mapActions,mapMutations} from "vuex"
export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Counts",
    data(){
        return {
            step:1
        }
    },
    computed:{
        ...mapState(["n"]),
        ...mapGetters({bigNum:"numBig",personNum:"personNum"})
    }
    ,
    methods:{
        // 傳入對象是常規(guī)寫法,當(dāng)對象中的鍵值相等時,可以用傳入列表的方式進(jìn)行傳參
        // 例如上面的mapState(["n"])
        ...mapMutations({addNum:"add_Num",subNum:"sub_Num"}),
        ...mapActions({oddNum:"odd_Num",longTimeAdd:"long_Time_Add"})
    }
}
</script>
<style>
.container1>*{
    margin-left: 10px; 
}
</style>

person組件

<template>
  <div>
      <h2>目前的計算結(jié)果為{{n}}</h2>
      //監(jiān)聽的鍵盤事件,當(dāng)輸入enter時添加用戶
      <input v-model="tempname" @keydown.enter="add_Person(tempname)">
      <ul>
          <li v-for="p in personList" :key="p.id">
              學(xué)生id:{{p.id}} 學(xué)生姓名:{{p.name}}
          </li>
      </ul>
  </div>
</template>
<script>
import {mapState,mapActions} from "vuex"
export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Persons",
    data(){
        return {
            tempname:""
        }
    },
    computed:{
        ...mapState(["n","personList"])
    },
    methods:{
        ...mapActions(["add_Person"])
    }
}
</script>
<style>
</style>

五、模塊化使用vuex

如果不按照數(shù)據(jù)功能對數(shù)據(jù)進(jìn)行模塊劃分,那么vuex將會顯得非常雜亂,我們希望vuex可以根據(jù)數(shù)據(jù)的不同作用將其進(jìn)行模塊化,便于我們管理,對于接下來的代碼大家需要熟悉的是如何使用劃分后的函數(shù)、函數(shù)映射。

劃分后的代碼大概長這個樣子,其中store中的index會將count.js與person.js引入并使用。vue代碼中使用vuex依舊是引入index.js,值得注意的是進(jìn)行模塊劃分后的vuex,在使用時跟以往有了不同。詳細(xì)看代碼

index.js

import Vue from "vue"
import Vuex from "vuex"
import counts from "./count"
import person from "./person"
Vue.use(Vuex)
export default new Vuex.Store({
    modules:{
        counts,
        person
    }
})

count.js

// import axios from "axios"
export default{
    namespaced:true,
    actions:{
    /* ... */
    },
    mutations:{
    /* ... */
    },
    state:{
        n:0,
    },
    getters:{
        numBig(state){
            return state.n*10
        }
    }
}

person.js

import {nanoid}  from "nanoid"
export default{
    namespaced:true,
    actions:{
    /* ... */
    },
    mutations:{
    /* ... */
    },
    state:{
        personList:[
            {
                id:"0001",
                name:"張三"
            }
        ]
    },
    getters:{
        personNum(state){
            return state.personList.length
            // console.log("index"+state.personList.length)
        }
    }
}

count.vue

<template>
  <div>
      <h2>目前的數(shù)值結(jié)果是:{{n}}</h2>
      <h2>放大后的數(shù)值結(jié)果是:{{bigNum}}</h2>
      <div class="container1">
          <select v-model.number="step">
              <option value="1">1</option>
              <option value="2">2</option>
              <option value="3">3</option>
          </select>
          <button @click="addNum(step)">增加</button>
          <button @click="subNum(step)">減少</button>
          <button @click="oddNum(step)">偶數(shù)再加</button>
          <button @click="longTimeAdd(step)">延遲增加</button>
      </div>
      <h2>當(dāng)前的總?cè)藬?shù)為{{personNum}}</h2>
  </div>
</template>
<script>
import {mapState,mapGetters,mapActions,mapMutations} from "vuex"
export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Counts",
    data(){
        return {
            step:1
        }
    },
    computed:{
        ...mapState("counts",["n"]),
        ...mapGetters("counts",{bigNum:"numBig"}),
        ...mapGetters("person",{personNum:"personNum"})
    }
    ,
    methods:{
        // 傳入對象是常規(guī)寫法,當(dāng)對象中的鍵值相等時,可以用傳入列表的方式進(jìn)行傳參
        // 例如上面的mapState(["n"])
        ...mapMutations("counts",{addNum:"add_Num",subNum:"sub_Num"}),
        ...mapActions("counts",{oddNum:"odd_Num",longTimeAdd:"long_Time_Add"})
    }
}
</script>
<style>
.container1>*{
    margin-left: 10px; 
}
</style>

persons.vue

<template>
  <div>
      <h2>目前的計算結(jié)果為{{n}}</h2>
      <input v-model="tempname" @keydown.enter="addPerson(tempname)">
      <button v-if="tag" @click="tag=!tag">目前可增加任意姓氏</button>
      <button v-if="!tag" @click="tag=!tag">目前只可以添加王氏</button>
      <ul>
          <li v-for="p in personList" :key="p.id">
              學(xué)生id:{{p.id}} 學(xué)生姓名:{{p.name}}
          </li>
      </ul>
  </div>
</template>
<script>
import {mapState,mapActions} from "vuex"
export default {
    // eslint-disable-next-line vue/multi-word-component-names
    name:"Persons",
    data(){
        return {
            tag:true,
            tempname:""
        }
    },
    computed:{
        ...mapState("counts",["n"]),
        ...mapState("person",["personList"])
    },
    methods:{
        ...mapActions("person",["add_Person"]),
        addPerson(){
            if (this.tempname===""){
                return ""
            }
            if(this.tag){
                // 映射出來的函數(shù)
                this.add_Person(this.tempname)
            }else{
//[Vue warn]: Error in v-on handler: "TypeError: this.addPersonWang is not a function"
// 如果沒有使用映射的話,不能這樣使用
// this.addPersonWang(this.tempname)
                // 正確的使用方式(使用模塊命名空間進(jìn)行限定)
                this.$store.dispatch("person/addPersonWang",this.tempname)
            }
            this.tempname=""
        },
    }
}
</script>
<style>
</style>

除此之外還可以通過下面方法獲取到vuex中的state中的屬性。

this.$store.state.模塊名.屬性

this.$store.state.loginModel.userInfo

到此這篇關(guān)于Vue組件間通信的實現(xiàn)方法講解的文章就介紹到這了,更多相關(guān)Vue組件間通信內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vuex+axios+element-ui實現(xiàn)頁面請求loading操作示例

    vuex+axios+element-ui實現(xiàn)頁面請求loading操作示例

    這篇文章主要介紹了vuex+axios+element-ui實現(xiàn)頁面請求loading操作,結(jié)合實例形式分析了vuex+axios+element-ui實現(xiàn)頁面請求過程中l(wèi)oading遮罩層相關(guān)操作技巧與使用注意事項,需要的朋友可以參考下
    2020-02-02
  • 關(guān)于TypeScript的踩坑記錄

    關(guān)于TypeScript的踩坑記錄

    這篇文章主要介紹了關(guān)于TypeScript的踩坑記錄,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • vue-antd?form組件封裝全過程

    vue-antd?form組件封裝全過程

    這篇文章主要介紹了vue-antd?form組件封裝全過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • vue.js指令v-model使用方法

    vue.js指令v-model使用方法

    這篇文章主要為大家詳細(xì)介紹了vue.js指令v-model的使用方法 ,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • Vue實現(xiàn)拖拽改變列表順序詳解

    Vue實現(xiàn)拖拽改變列表順序詳解

    這篇文章主要為大家詳細(xì)介紹了Vue實現(xiàn)拖拽改變列表順序的相關(guān)知識,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-04-04
  • vue路由攔截及頁面跳轉(zhuǎn)的設(shè)置方法

    vue路由攔截及頁面跳轉(zhuǎn)的設(shè)置方法

    這篇文章主要介紹了vue路由攔截及頁面跳轉(zhuǎn)的設(shè)置方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-05-05
  • 關(guān)于element-ui?單選框默認(rèn)值不選中的解決

    關(guān)于element-ui?單選框默認(rèn)值不選中的解決

    這篇文章主要介紹了關(guān)于element-ui?單選框默認(rèn)值不選中的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • 一文帶你了解Vue?和?React的區(qū)別

    一文帶你了解Vue?和?React的區(qū)別

    這篇文章主要介紹了Vue和React的區(qū)別,畢竟是兩個框架,不像兩個?API,要說細(xì)節(jié)上的區(qū)別就太多太多了,本文就簡單的帶大家說說Vue?和?React?的區(qū)別,需要的朋友可以參考下
    2023-05-05
  • Vue路由管理器Vue-router的使用方法詳解

    Vue路由管理器Vue-router的使用方法詳解

    本文將詳細(xì)介紹Vue路由管理器Vue-router的使用方法詳解,需要的朋友可以參考下
    2020-02-02
  • vue中__ob__:?Observer的踩坑記錄

    vue中__ob__:?Observer的踩坑記錄

    這篇文章主要介紹了vue中__ob__:?Observer的踩坑記錄,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-10-10

最新評論