Vue2之Vuex

文章目錄

  • 數據準備
    • 新建項目
    • 選擇模塊安裝
    • vscode工具打開 刪除無用文件
      • 刪除src/assets文件下的所有內容
      • 刪除src/components文件下的所有內容
      • 修改src/app.vue
      • vscode運行項目
  • 一、 概述
    • 1.是什么
    • 2. 使用場景
    • 3.優勢
    • 4 Vuex流程圖
    • 5.注意:
  • 二、需求: 多組件共享數據
    • 創建三個組件, 目錄如下
    • 源代碼如下
      • Son1.vue
      • Son2.vue
      • App.vue
      • main.js不變
    • 說明
  • 三、vuex 的使用 - 創建倉庫
    • 1.安裝 vuex
    • 2.新建 store/index.js 專門存放 vuex
    • 3.創建倉庫 store/index.js
    • 4 在 main.js 中導入掛載到 Vue 實例上
    • 5.測試打印Vuex
  • 四、核心概念 - state 狀態
    • 4.1 概念
    • 4.2 store中定義state屬性提供數據
    • 4.3 訪問Vuex中的數據
    • 4.4 組件通過$store訪問Vuex中的數據
      • 4.4.1 模板中使用
      • 4.4.2. 組件邏輯中使用
      • 4.4.3 js文件中使用
      • 4.4.4 修改src/components/Son1.vue
    • 4.5 組件通過mapState獲取 state中的數據
      • 4.5.1 mapState作用
      • 4.5.2 修改src/components/Son2.vue
      • 4.5.3 運行結果
  • 五、開啟嚴格模式及Vuex的單項數據流
    • 1.目標
    • 2.直接在組件中修改Vuex中state的值
      • Son1.vue
      • 運行結果
    • 3.開啟嚴格模式
      • 嚴格模式有什么用
      • 運行結果
  • 六、mutations+mapMutations同步修改倉庫屬性的值
    • 6.1 概念
    • 6.2 store中定義mutations
      • 6.2.1 語法
      • 6.2.2 代碼:修改src/store/index.js
    • 6.3 組件中使用$store.emit()調用mutations方法
      • 6.3.1 修改src/components/Son1.vue
      • 6.3.2 運行結果
    • 6.4 組件中使用mapMutations輔助函數調用mutations
      • 6.4.1 mapMutations用法
      • 6.4.2 代碼實現
      • 6.4.3 運行結果
  • 七、actions+mapActions異步修改倉庫屬性的值
    • 7.1 概念
    • 7.2 store中定義actions
      • 7.2.1 語法
      • 7.2.2 代碼:修改src/store/index.js
    • 7.3 組件中使用$store.dispatch()調用actions的方法
      • 7.3.1 語法
      • 7.3.2 修改src/components/Son1.vue
      • 7.3.3 運行結果
    • 7.4 組件中使用mapActions調用actions的方法
      • 7.4.1 mapActions語法
      • 7.4.2 代碼實現
      • 7.4.3 運行結果
  • 八、核心概念-getters
    • 8.1 概念getters
    • 8.2 store中定義getters
      • 8.2.1 語法
      • 8.2.2 代碼:修改src/store/index.js
    • 8.3 組件中使用$store.commit調用getters的方法
      • 8.3.1 語法
      • 8.3.2 修改src/components/Son1.vue
      • 8.3.3 運行結果
    • 8.4 組件中使用mapGetters調用getters的方法
      • 8.4.1 mapGetters語法
      • 8.4.2 代碼實現
      • 8.4.3 運行結果
  • 9 前面四個屬性的總結
  • 十、核心概念 - 模塊 module
    • 10.1 概念
    • 10.2 模塊定義
      • 10.2.1 新建src/store/modules/user.js
      • 10.2.2 新建src/store/modules/setting.js
      • 10.2.3 修改src/store/index.js
      • 10.2.4 修改src/components/Son1.vue
      • 10.2.5 修改src/components/Son2.vue
      • 10.2.6 運行結果如下
    • 10.3 命名空間
      • 10.3.1 什么是命名空間
      • 10.3.2 如何在子模塊中開啟命名空間
    • 10.4 分模塊的state使用和獲取
    • 10.5 分模塊的mutations使用和獲取
    • 10.6 分模塊的actions使用和獲取
    • 10.7 分模塊的getters使用和獲取
    • 10.8 代碼演示
      • 修改src/components/Son1.vue
      • 修改src/components/Son2.vue
  • 總結
    • 流程圖
    • 不使用分模塊的寫法
    • 使用分模塊寫法
    • 開啟嚴格模式
    • 開啟命名空間

數據準備

新建項目

  1. 檢查版本
    node版本:20.18.0
    @vue/cli版本:5.0.8
  2. 新建文件夾,輸入cmd回車打開命令行窗口
    在這里插入圖片描述
  3. 命令行窗口:輸入指令vue create 項目名
    在這里插入圖片描述

選擇模塊安裝

在這里插入圖片描述

vscode工具打開 刪除無用文件

刪除src/assets文件下的所有內容

刪除src/components文件下的所有內容

修改src/app.vue

<template><div id="app"></div>
</template><script>export default {name: 'App'
}
</script><style lang="scss">
</style>

vscode運行項目

快捷鍵打開終端Ctrl + Shift + 反引號 打開終端。反引號是tab鍵上面那個
運行如下指令啟動項目

npm run serve

一、 概述

1.是什么

Vuex 是一個 Vue 的 狀態管理工具,狀態就是數據。
官網如下:https://vuex.vuejs.org/zh/

大白話:Vuex 是一個插件,可以幫我們管理 Vue 通用的數據 (多組件共享的數據)。例如:購物車數據 個人信息數

2. 使用場景

  • 某個狀態 在 很多個組件 來使用 (個人信息)
    主頁需要展示 XXX訂單需要寫你的名字等等。
  • 多個組件 共同維護 一份數據 (購物車)
    在這里插入圖片描述

3.優勢

  • 共同維護一份數據,數據集中化管理
  • 響應式變化
  • 操作簡潔 (vuex提供了一些輔助函數)
    在這里插入圖片描述

4 Vuex流程圖

這個圖等講完后就能看懂了。
在這里插入圖片描述

5.注意:

官方原文:

  • 不是所有的場景都適用于vuex,只有在必要的時候才使用vuex
  • 使用了vuex之后,會附加更多的框架中的概念進來,增加了項目的復雜度 (數據的操作更便捷,數據的流動更清晰)

Vuex就像《近視眼鏡》, 你自然會知道什么時候需要用它~

二、需求: 多組件共享數據

目標:基于腳手架創建項目,構建 vuex 多組件數據共享環境
在這里插入圖片描述
效果是三個組件共享一份數據:

  • 任意一個組件都可以修改數據
  • 三個組件的數據是同步的

創建三個組件, 目錄如下

|-components
|--Son1.vue
|--Son2.vue
|-App.vue

源代碼如下

Son1.vue

<template><div class="box"><h2>Son1 子組件</h2>從vuex中獲取的值: <label></label><br><button>值 + 1</button></div>
</template><script>
export default {name: 'Son1Com'
}
</script><style lang="css" scoped>
.box{border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

Son2.vue

<template><div class="box"><h2>Son2 子組件</h2>從vuex中獲取的值:<label></label><br /><button>值 - 1</button></div>
</template><script>
export default {name: 'Son2Com'
}
</script><style lang="css" scoped>
.box {border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

App.vue

App.vue在入口組件中引入 Son1 和 Son2 這兩個子組件

<template><div id="app"><h1>根組件</h1><input type="text"><Son1></Son1><hr><Son2></Son2></div>
</template><script>
import Son1 from './components/Son1.vue'
import Son2 from './components/Son2.vue'export default {name: 'app',data: function () {return {}},components: {Son1,Son2}
}
</script><style>
#app {width: 600px;margin: 20px auto;border: 3px solid #ccc;border-radius: 3px;padding: 10px;
}
</style>

main.js不變

import Vue from 'vue'
import App from './App.vue'Vue.config.productionTip = falsenew Vue({render: h => h(App)
}).$mount('#app')

說明

在這里插入圖片描述

上圖中的Son1使用原始方法獲取值Vuex的值 進行演示講解
Son2使用輔助函數的方式獲取值Vuex的值 進行演示講解

三、vuex 的使用 - 創建倉庫

在這里插入圖片描述

1.安裝 vuex

安裝vuex與vue-router類似,vuex是一個獨立存在的插件,如果腳手架初始化沒有選 vuex,就需要額外安裝。

yarn add vuex@3 或者 npm i vuex@3

注意

  • vue2 安裝Vuex3.0 版本 Router 3.0 版本
  • vue3 安裝Vuex4.0 版本 Router 4.0 版本

2.新建 store/index.js 專門存放 vuex

為了維護項目目錄的整潔,在src目錄下新建一個store目錄其下放置一個index.js文件。 (和 router/index.js 類似)

在這里插入圖片描述

3.創建倉庫 store/index.js

// 導入 vue
import Vue from 'vue'
// 導入 vuex
import Vuex from 'vuex'
// vuex也是vue的插件, 需要use一下, 進行插件的安裝初始化
Vue.use(Vuex)// 創建倉庫 store
const store = new Vuex.Store()// 導出倉庫
export default store

4 在 main.js 中導入掛載到 Vue 實例上

import Vue from 'vue'
import App from './App.vue'
import store from './store'Vue.config.productionTip = falsenew Vue({render: h => h(App),store
}).$mount('#app')

此刻起, 就成功創建了一個 空倉庫!!

5.測試打印Vuex

App.vue

created(){console.log(this.$store)
}

在這里插入圖片描述

四、核心概念 - state 狀態

4.1 概念

在這里插入圖片描述

State提供唯一的公共數據源,所有共享的數據都要統一放到Store中的State中存儲。即上圖的State—>Vue Components

4.2 store中定義state屬性提供數據

打開項目中的store.js文件,在state對象中可以添加我們要共享的數據。
修改src/store/index.js

// 導入 vue
import Vue from 'vue'
// 導入 vuex
import Vuex from 'vuex'
// vuex也是vue的插件, 需要use一下, 進行插件的安裝初始化
Vue.use(Vuex)// 創建倉庫 store
const store = new Vuex.Store({// state 狀態, 即數據, 類似于vue組件中的data,// 區別:// 1.data 是組件自己的數據, // 2.state 中的數據整個vue項目的組件都能訪問到state: {count: 101}
})
// 導出倉庫
export default store

4.3 訪問Vuex中的數據

問題: 如何在組件中獲取count?

  1. 通過$store直接訪問 —> {{ $store.state.count }}
  2. 通過輔助函數mapState 映射計算屬性 —> {{ count }}(后面講)

4.4 組件通過$store訪問Vuex中的數據

獲取 store:1.Vue模板中獲取 this.$store2.js文件中獲取 import 導入 store模板中:     {{ $store.state.xxx }}
組件邏輯中:  this.$store.state.xxx
JS模塊中:   store.state.xxx

4.4.1 模板中使用

組件中可以使用 $store 獲取到vuex中的store對象實例,可通過state屬性屬性獲取count, 如下

<h1>state的數據 - {{ $store.state.count }}</h1>

4.4.2. 組件邏輯中使用

將state屬性定義在計算屬性中 https://vuex.vuejs.org/zh/guide/state.html

<h1>state的數據 - {{ count }}</h1>
// 把state中數據,定義在組件內的計算屬性中computed: {count () {return this.$store.state.count}}

4.4.3 js文件中使用

//main.js
import store from "@/store"
console.log(store.state.count)

每次都像這樣一個個的提供計算屬性, 太麻煩了,我們有沒有簡單的語法幫我們獲取state中的值呢?

4.4.4 修改src/components/Son1.vue

<template><div class="box"><h2>Son1 子組件 使用原始方式獲取</h2><!-- 模板中使用 --><h4>從vuex中獲取count的值:{{$store.state.count}}</h4><!-- 組件邏輯中使用 --><h4>從vuex中獲取title的值:{{title}}</h4><br><button @click="handleAdd">值 + 1</button></div>
</template><script>
export default {name: 'Son1Com',computed: {title() {return this.$store.state.title}},methods: {handleAdd() {}}
}
</script><style lang="css" scoped>
.box{border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

4.5 組件通過mapState獲取 state中的數據

4.5.1 mapState作用

mapState是輔助函數,幫助我們把store中的數據 自動 映射到 組件的計算屬性中, 它屬于一種方便的用法

在這里插入圖片描述

4.5.2 修改src/components/Son2.vue

<template><div class="box"><h2>Son2 子組件 使用輔助函數方式獲取</h2><h4>從vuex中獲取count的值:{{count}}</h4><h4>從vuex中獲取title的值:{{title}}</h4><br /><button>值 - 1</button></div>
</template><script>
// 引入 mapState 輔助函數
import { mapState } from "vuex";
export default {name: 'Son2Com',computed: {...mapState(["count", "title"]),// 等價于// count () {//   return this.$store.state.count;// }// title () {//   return this.$store.state.title;// }},
}
</script><style lang="css" scoped>
.box {border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

4.5.3 運行結果

在這里插入圖片描述

五、開啟嚴格模式及Vuex的單項數據流

1.目標

明確 vuex 同樣遵循單向數據流,組件中不能直接修改倉庫的數據

2.直接在組件中修改Vuex中state的值

在這里插入圖片描述

Son1.vue

<template><div class="box"><h2>Son1 子組件</h2>從vuex中獲取的值: <label></label><br><!-- 1.綁定點擊事件 --><button @click="handleAdd">+ 1</button></div>
</template><script>
export default {name: 'Son1Com',// 定義方法methods: {handleAdd() {this.$store.state.count++}}
}
</script><style lang="css" scoped>
.box{border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

運行結果

不會報錯,這是因為沒有開啟嚴格模式
在這里插入圖片描述

3.開啟嚴格模式

嚴格模式有什么用

通過 strict: true 可以開啟嚴格模式,開啟嚴格模式后,直接修改state中的值會報錯

state數據的修改只能通過mutations,并且mutations必須是同步的

在這里插入圖片描述

運行結果

在這里插入圖片描述

六、mutations+mapMutations同步修改倉庫屬性的值

6.1 概念

上面說了state中的屬性值 不能直接修改就需要使用store的mutations屬性定義方法去修改state中的值。
在這里插入圖片描述

6.2 store中定義mutations

6.2.1 語法

注意事項

  1. mutations 修改state中的數據, 類似于vue組件中的methods
  2. mutations中屬性的方法
    + 第一個參數是當前store的state屬性
    + 第二個參數是payload(傳遞)載荷 用于傳遞參數
    + 注意:payload(傳遞)載荷只能有一個,想要傳遞多個參數要使用對象或者數組的形式。
  3. mutations中的方法, 必須是同步方法。同步方法是指js中的普通方法。異步方法下面會講。

6.2.2 代碼:修改src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)const store = new Vuex.Store({strict: true,state: {count: 101,title: 'hello world'},// mutations 修改state中的數據, 類似于vue組件中的methodsmutations: {// mutations中的方法, //    第一個參數是當前store的state屬性//    第二個參數是payload(傳遞)載荷  用于傳遞參數//      注意:payload(傳遞)載荷只能有一個,想要傳遞多個參數要使用對象或者數組的形式// mutations中的方法, 必須是同步方法// 傳單個參數addCount(state, num) {state.count += num},// 傳對象subCount(state, obj) {state.count -= obj.numconsole.log(obj.name);}},})export default store

6.3 組件中使用$store.emit()調用mutations方法

6.3.1 修改src/components/Son1.vue

由于上面在main.js全局已經全局掛在了所以不需要導入。

<template><div class="box"><h2>Son1 子組件 使用原始方式獲取</h2><!-- 模板中使用 --><h4>從vuex中獲取count的值:{{$store.state.count}}</h4><!-- 組件邏輯中使用 --><h4>從vuex中獲取title的值:{{title}}</h4><br><button @click="handleAdd">+ 1</button><button @click="$store.commit('addCount', 2)">+ 2</button><button @click="handleSub">- 1</button></div>
</template><script>
export default {name: 'Son1Com',computed: {title() {return this.$store.state.title}},methods: {handleAdd() {this.$store.commit('addCount', 1)},handleSub() {this.$store.commit('subCount', {num: 1, name: '張三'})}}
}
</script><style lang="css" scoped>
.box{border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

6.3.2 運行結果

在這里插入圖片描述

6.4 組件中使用mapMutations輔助函數調用mutations

6.4.1 mapMutations用法

<template><button @click="addCount(1)">值 + 1</button><button @click="subCount({num: 1, name: 'hello'})">值 - 1</button>
</template>
<script>
import { mapMutations} from "vuex";
export default {// ...methods: {...mapMutations(["addCount","subCount"])},
}
</script>

6.4.2 代碼實現

<template><div class="box"><h2>Son2 子組件 使用輔助函數方式獲取</h2><h4>從vuex中獲取count的值:{{count}}</h4><h4>從vuex中獲取title的值:{{title}}</h4><br /><button @click="addCount(1)">值 + 1</button><button @click="subCount({num: 1, name: 'hello'})">值 - 1</button></div>
</template><script>
// 引入 mapState 輔助函數
import { mapState,mapMutations} from "vuex";
export default {name: 'Son2Com',methods: {...mapMutations(["addCount","subCount"])},computed: {...mapState(["count", "title"]),// 等價于// count () {//   return this.$store.state.count;// }// title () {//   return this.$store.state.title;// }},
}
</script><style lang="css" scoped>
.box {border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

6.4.3 運行結果

在這里插入圖片描述

七、actions+mapActions異步修改倉庫屬性的值

7.1 概念

上面說了使用store的mutations屬性定義方法去修改state中的值mutations中的方法,。這個必須是同步方法。

什么是同步方法?:普通方法。
什么是異步方法?:異步方法是指那些不會阻塞主線程執行、允許程序在等待操作完成期間繼續執行其他任務的函數。
異步方法有哪些

  1. 回調函數(Callbacks):?將函數作為參數傳遞給另一個函數,在異步操作完成后被調用。這是最基礎的異步模式,但嵌套過多易導致“回調地獄”
    setTimeout(() => {console.log("異步操作完成");
    }, 1000);
    
  2. Promise:ES6引入的異步處理對象,表示一個異步操作的最終狀態(pending/fulfilled/rejected)。通過鏈式調用(.then()/.catch())管理依賴關系,解決回調嵌套問題 。
    const promise = new Promise((resolve, reject) => {setTimeout(() => resolve("成功"), 1000);
    });
    promise.then(result => console.log(result));
    
  3. ?Async/Await?:ES8基于Promise的語法糖。async標記的函數返回Promise,await暫停函數執行直至Promise完成,使異步代碼寫法類似同步
    async function fetchData() {try {const data = await fetch("/api/data");return data.json();} catch (error) {console.error(error);}
    }
    

作用:mapActions 是把位于 actions中的方法提取了出來,映射到組件methods中。

mutations是同步更新數據 (便于監測數據的變化, 更新視圖等, 方便于調試工具查看變化)。
actions則負責進行異步操作。里面的方法是異步的。

流程如下圖所示。異步修改和同步修改的流程如下。
在這里插入圖片描述

7.2 store中定義actions

7.2.1 語法

// ....
const store = new Vuex.Store({// ...mutations: {addCount(state, num) {state.count += num}},actions: {addCountAsync(context, num) {// 1秒后調用mutations中的addCount方法setTimeout(() => {context.commit('addCount', num)}, 1000)}}// ...
})
  1. actions中的方法,
    • 第一個參數是context 上下文屬性,
      • 包含了 state(上面的state),
        commit(用于調用mutations中的方法),
        dispatch(用于調用actions中的方法),
        getters(后面講),
        rootState, rootGetters
    • 第二個參數是payload(傳遞)載荷 用于傳遞參數
      • 注意:payload(傳遞)載荷只能有一個,想要傳遞多個參數要使用對象或者數組的形式
  2. actions中的方法, 寫異步方法

7.2.2 代碼:修改src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)const store = new Vuex.Store({strict: true,state: {count: 101,title: 'hello world'},// mutations 修改state中的數據, 類似于vue組件中的methodsmutations: {// mutations中的方法, //    第一個參數是當前store的state屬性//    第二個參數是payload(傳遞)載荷  用于傳遞參數//      注意:payload(傳遞)載荷只能有一個,想要傳遞多個參數要使用對象或者數組的形式// mutations中的方法, 必須是同步方法// 傳單個參數addCount(state, num) {state.count += num},// 傳對象subCount(state, obj) {state.count -= obj.numconsole.log(obj.name);}},// actions 類似于mutations, 但是actions中可以寫異步方法actions: {// actions中的方法, //    第一個參數是context 上下文屬性, //       包含了 state(上面的state), //              commit(用于調用mutations中的方法), //              dispatch(用于調用actions中的方法),//              getters(后面講), //              rootState, rootGetters//    第二個參數是payload(傳遞)載荷  用于傳遞參數//       注意:payload(傳遞)載荷只能有一個,想要傳遞多個參數要使用對象或者數組的形式// actions中的方法, 寫異步方法addCountAsync(context, num) {// console.log(context);// 1秒后調用mutations中的addCount方法setTimeout(() => {context.commit('addCount', num)}, 1000)},subCountAsync(context, obj) {// 1秒后調用mutations中的subCount方法setTimeout(() => {context.commit('subCount', obj);}, 1000)}}})
export default store

7.3 組件中使用$store.dispatch()調用actions的方法

7.3.1 語法

<template><div><!-- $store.dispatch調用actions中的方法 --><button @click="$store.dispatch('addCountAsync', 2)">1秒后值 + 2</button><button @click="handleAddAsync()">1秒后值 - 2</button></div>
</template><script>
export default {methods: {handleAddAsync() {this.$store.dispatch('subCountAsync', {num: 2, name: '李四'})}}
}
</script>

7.3.2 修改src/components/Son1.vue

<template><div class="box"><h2>Son1 子組件 使用原始方式獲取</h2><!-- 模板中使用 --><h4>從vuex中獲取count的值:{{$store.state.count}}</h4><!-- 組件邏輯中使用 --><h4>從vuex中獲取title的值:{{title}}</h4><br><button @click="handleAdd">值 + 1</button><button @click="$store.commit('addCount', 2)">值 + 2</button><button @click="handleSub">值 - 1</button><!-- $store.dispatch調用actions中的方法 --><button @click="$store.dispatch('addCountAsync', 2)">1秒后值 + 2</button><button @click="handleAddAsync()">1秒后值 - 2</button></div>
</template><script>
export default {name: 'Son1Com',computed: {title() {return this.$store.state.title}},methods: {handleAdd() {this.$store.commit('addCount', 1)},handleSub() {this.$store.commit('subCount', {num: 1, name: '張三'})},handleAddAsync() {this.$store.dispatch('subCountAsync', {num: 2, name: '李四'})}}
}
</script><style lang="css" scoped>
.box{border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

7.3.3 運行結果

在這里插入圖片描述

7.4 組件中使用mapActions調用actions的方法

7.4.1 mapActions語法

<template><div></div>
</template><script>
export default {}
</script>

7.4.2 代碼實現

<template><div class="box"><h2>Son2 子組件 使用輔助函數方式獲取</h2><h4>從vuex中獲取count的值:{{count}}</h4><h4>從vuex中獲取title的值:{{title}}</h4><br /><button @click="addCount(1)">值 + 1</button><button @click="subCount({num: 1, name: 'hello'})">值 - 1</button><!-- mapActions輔助函數調用actions中的方法 --><button @click="addCountAsync(1)">一秒后值 + 1</button><button @click="subCountAsync({num: 1, name: 'hello'})">一秒后值 - 1</button></div>
</template><script>
// 引入 mapState 輔助函數
import { mapState,mapMutations, mapActions} from "vuex";
export default {name: 'Son2Com',methods: {...mapMutations(["addCount","subCount"]),...mapActions(["addCountAsync","subCountAsync"]),// 等價于// addCountAsync () {//   this.$store.dispatch("addCountAsync", 1);// }// subCountAsync () {//   this.$store.dispatch("subCountAsync",{num: 1, name: 'hello'});// }},computed: {...mapState(["count", "title"]),},
}
</script><style lang="css" scoped>
.box {border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

7.4.3 運行結果

在這里插入圖片描述

八、核心概念-getters

8.1 概念getters

除了state之外,有時我們還需要從state中派生出一些狀態,這些狀態是依賴state的,此時會用到getters。
應用1:state中定義了list,為 1-10 的數組,組件中,需要顯示所有大于5的數據。當state中的數據修改后,會影響getters中的屬性。
應用2:計算購物車的總價格。
在這里插入圖片描述

8.2 store中定義getters

8.2.1 語法

// ....
const store = new Vuex.Store({// ...state: {items: [ // 商品數組{ id: 1, name: "iPhone", price: 5000, quantity: 2 },{ id: 2, name: "MacBook", price: 12000, quantity: 1 }]},mutations: {// 添加商品addItem(state, item) {state.items.push(item)},// 刪除商品removeItem(state, id) {state.items = state.items.filter(item => item.id !== id)}},// getters 用來獲取state中的數據, 類似于vue組件中的computedgetters: {// getters中的方法, //    第一個參數是state屬性//    第二個參數是getters屬性// getters中的方法, 必須是同步方法// 計算items數組中所有商品的總價格totalPrice: (state) => {return state.items.reduce((total, item) => {return total + item.price * item.quantity;}, 0).toFixed(2); // 保留兩位小數},// 計算items數組中所有商品的平均價格averagePrice: (state, getters) => getters.totalPrice / state.items.length}})// ...

8.2.2 代碼:修改src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)const store = new Vuex.Store({strict: true,state: {count: 101,title: 'hello world',items: [ // 商品數組{ id: 1, name: "iPhone", price: 5000, quantity: 2 },{ id: 2, name: "MacBook", price: 12000, quantity: 1 }]},mutations: {addCount(state, num) {state.count += num},subCount(state, obj) {state.count -= obj.numconsole.log(obj.name);},// 添加商品addItem(state, item) {state.items.push(item)},// 刪除商品removeItem(state, id) {state.items = state.items.filter(item => item.id !== id)}},actions: {addCountAsync(context, num) {setTimeout(() => {context.commit('addCount', num)}, 1000)},subCountAsync(context, obj) {setTimeout(() => {context.commit('subCount', obj);}, 1000)},},// getters 用來獲取state中的數據, 類似于vue組件中的computedgetters: {// getters中的方法, //    第一個參數是state屬性//    第二個參數是getters屬性// getters中的方法, 必須是同步方法// 計算items數組中所有商品的總價格totalPrice: (state) => {return state.items.reduce((total, item) => {return total + item.price * item.quantity;}, 0).toFixed(2); // 保留兩位小數},// 計算items數組中所有商品的平均價格averagePrice: (state, getters) => getters.totalPrice / state.items.length}})export default store

8.3 組件中使用$store.commit調用getters的方法

8.3.1 語法

<template><div class="box"><!-- 在js中要加this進行調用,即this.$store.getters.totalPrice --><h4>從vuex中獲取items的值:{{$store.state.items}}</h4><button @click="$store.commit('addItem', {id: 3, name: 'AirPods', price: 1000, quantity: 1})">添加商品</button><button @click="$store.commit('removeItem', 1)">刪除商品</button><br><h4>從vuex中獲取items的總價格:{{$store.getters.totalPrice}}</h4><h4>從vuex中獲取items的平均價格:{{$store.getters.averagePrice}}</h4></div>
</template>

8.3.2 修改src/components/Son1.vue

<template><div class="box"><h2>Son1 子組件 使用原始方式獲取</h2><!-- 模板中使用 --><h4>從vuex中獲取count的值:{{$store.state.count}}</h4><!-- 組件邏輯中使用 --><h4>從vuex中獲取title的值:{{title}}</h4><br><button @click="handleAdd">值 + 1</button><button @click="$store.commit('addCount', 2)">值 + 2</button><button @click="handleSub">值 - 1</button><!-- $store.dispatch調用actions中的方法 --><button @click="$store.dispatch('addCountAsync', 2)">1秒后值 + 2</button><button @click="handleAddAsync()">1秒后值 - 2</button><br><h4>從vuex中獲取items的值:{{$store.state.items}}</h4><button @click="$store.commit('addItem', {id: 3, name: 'AirPods', price: 1000, quantity: 1})">添加商品</button><button @click="$store.commit('removeItem', 1)">刪除商品</button><br><h4>從vuex中獲取items的總價格:{{$store.getters.totalPrice}}</h4><h4>從vuex中獲取items的平均價格:{{$store.getters.averagePrice}}</h4></div>
</template><script>
export default {name: 'Son1Com',computed: {title() {return this.$store.state.title}},methods: {handleAdd() {this.$store.commit('addCount', 1)},handleSub() {this.$store.commit('subCount', {num: 1, name: '張三'})},handleAddAsync() {this.$store.dispatch('subCountAsync', {num: 2, name: '李四'})}}
}
</script><style lang="css" scoped>
.box{border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

8.3.3 運行結果

在這里插入圖片描述

8.4 組件中使用mapGetters調用getters的方法

8.4.1 mapGetters語法

<template><div class="box"><h4>{{items}}</h4><!-- 這里參數太長 我創建addhandle添加商品 --><button @click="addhandle()">添加商品</button><button @click="removeItem(1)">刪除商品</button><br /><h4>從vuex中獲取items數組中所有商品的總價格:{{totalPrice}}</h4><h4>從vuex中獲取items數組中所有商品的平均價格:{{averagePrice}}</h4></div>
</template><script>
// 引入 mapState 輔助函數
import { mapState,mapMutations, mapActions, mapGetters} from "vuex";
export default {name: 'Son2Com',computed: {// 將items數組中的數據映射到當前組件中...mapState(["items"]),// getters 用來獲取state中的數據, 類似于vue組件中的computed...mapGetters(["totalPrice", "averagePrice"]),},methods: {// 將 添加商品 和 刪除商品 引入。...mapMutations(["addItem","removeItem"]),// 添加商品addhandle() {this.addItem({id: 3, name: 'AirPods', price: 1000, quantity: 1});}}}
</script>

8.4.2 代碼實現

<template><div class="box"><h2>Son2 子組件 使用輔助函數方式獲取</h2><h4>從vuex中獲取count的值:{{count}}</h4><h4>從vuex中獲取title的值:{{title}}</h4><br /><button @click="addCount(1)">值 + 1</button><button @click="subCount({num: 1, name: 'hello'})">值 - 1</button><!-- mapActions輔助函數調用actions中的方法 --><button @click="addCountAsync(1)">一秒后值 + 1</button><button @click="subCountAsync({num: 1, name: 'hello'})">一秒后值 - 1</button><br /><h4>{{items}}</h4><!-- 這里參數太長 我創建addhandle添加商品 --><button @click="addhandle()">添加商品</button><button @click="removeItem(1)">刪除商品</button><br /><h4>從vuex中獲取items數組中所有商品的總價格:{{totalPrice}}</h4><h4>從vuex中獲取items數組中所有商品的平均價格:{{averagePrice}}</h4></div>
</template><script>
// 引入 mapState 輔助函數
import { mapState,mapMutations, mapActions, mapGetters} from "vuex";
export default {name: 'Son2Com',computed: {// 將items數組中的數據映射到當前組件中...mapState(["count", "title", "items"]),// getters 用來獲取state中的數據, 類似于vue組件中的computed...mapGetters(["totalPrice", "averagePrice"]),},methods: {// 將 添加商品 和 刪除商品 引入。...mapMutations(["addCount","subCount","addItem","removeItem"]),...mapActions(["addCountAsync","subCountAsync"]),// 添加商品addhandle() {this.addItem({id: 3, name: 'AirPods', price: 1000, quantity: 1});}}}
</script><style lang="css" scoped>
.box {border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

8.4.3 運行結果

在這里插入圖片描述

9 前面四個屬性的總結

在這里插入圖片描述

十、核心概念 - 模塊 module

10.1 概念

由于使用單一狀態樹,應用的所有狀態會集中到一個比較大的對象。當應用變得非常復雜時,store 對象就有可能變得相當臃腫。

這句話的意思是,如果把所有的狀態都放在state中,當項目變得越來越大的時候,Vuex會變得越來越難以維護

由此,又有了Vuex的模塊化在這里插入圖片描述

10.2 模塊定義

定義兩個模塊 usersetting。這兩個模塊分別是用戶信息和設置信息。

10.2.1 新建src/store/modules/user.js

user中管理用戶的信息狀態

const state = {userInfo: {name: 'zs',age: 18}
}const mutations = {}const actions = {}const getters = {}export default {state,mutations,actions,getters
}

10.2.2 新建src/store/modules/setting.js

setting中管理項目應用的 主題色 theme,描述 desc

const state = {theme: 'dark',desc: '描述真呀真不錯'
}const mutations = {}const actions = {}const getters = {}export default {state,mutations,actions,getters
}

10.2.3 修改src/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
import setting from './modules/setting'
Vue.use(Vuex)const store = new Vuex.Store({strict: true,state: {count: 101,},mutations: {},actions: {},getters: {},modules: {user,setting}})export default store

10.2.4 修改src/components/Son1.vue

<template><div class="box"><h2>Son1 子組件 使用原始方式獲取</h2></div>
</template><script>
export default {computed: {},methods: {}
}
</script><style lang="css" scoped>
.box{border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

10.2.5 修改src/components/Son2.vue

<template><div class="box"><h2>Son2 子組件 使用輔助函數方式獲取</h2></div>
</template><script>
export default {computed: {},methods: {},
};
</script><style lang="css" scoped>
.box {border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

10.2.6 運行結果如下

在這里插入圖片描述

10.3 命名空間

10.3.1 什么是命名空間

我們知道上面雖然都分模塊了,但是他們都還是會掛到根級別的state、getters、mutations、actions下。

如果我的user模塊和setting模塊下的state下都有一個叫做aa的屬性。此時我使用輔助函數調用這個屬性mapState(['aa']),代碼無法識別這個aa是user模塊下的aa屬性 還是setting模塊下的aa屬性。
在這里插入圖片描述

開啟命名空間
解決不同模塊的state、getters、mutations、actions重名問題
一般命名空間都是開啟的

10.3.2 如何在子模塊中開啟命名空間

const state = {userInfo: {name: 'zs',age: 18}
}const mutations = {}const actions = {}const getters = {}export default {// 開啟命名空間// 1. 解決不同模塊命名沖突// 2. 解決不同模塊的state、getters、mutations、actions重名問題namespaced: true,state,mutations,actions,getters
}

10.4 分模塊的state使用和獲取

盡管已經分模塊了,但其實子模塊的狀態,還是會掛到根級別的 state 中,屬性名就是模塊名使用模塊中的數據
在這里插入圖片描述
① 直接通過模塊名訪問 $store.state.模塊名.xxx
② 通過 mapState 映射
默認根級別的映射 mapState([ 'xxx' ])
子模塊的映射 mapState('模塊名', ['xxx','xxx'...]) - 需要開啟命名空間

10.5 分模塊的mutations使用和獲取

注意:默認模塊中的 mutation 和 actions 會被掛載到全局,需要開啟命名空間,才會掛載到子模塊。

調用子模塊中 mutation:
① 直接通過 store 調用 $store.commit('模塊名/xxx', 額外參數)
② 通過 mapMutations 映射
默認根級別的映射 mapMutations([ 'xxx' ])
子模塊的映射 mapMutations('模塊名', ['xxx','xxx'...]) - 需要開啟命名空間

10.6 分模塊的actions使用和獲取

注意:默認模塊中的 mutation 和 actions 會被掛載到全局,需要開啟命名空間,才會掛載到子模塊。

調用子模塊中 action :
① 直接通過 store 調用 $store.dispatch('模塊名/xxx ', 額外參數)
② 通過 mapActions 映射
默認根級別的映射 mapActions([ ‘xxx’ ])
子模塊的映射 mapActions(‘模塊名’, [‘xxx’,‘xxx’]) - 需要開啟命名空間

10.7 分模塊的getters使用和獲取

使用模塊中 getters 中的數據:
① 直接通過模塊名訪問 $store.getters['模塊名/xxx']
注意:沒使用模塊之前是使用的 $store.getters.xxx。
注意:使用模塊后不使用的 $store.getters.某塊名.xxx,原因為這里是

this.$store.getters的值為
{主模塊名:屬性字模塊名/xxx: 屬性
}
// 我們$store.getters.字模塊名/xxx會報錯因為有 / 這個圖書字符。
// 因此使用$store.getters['模塊名/xxx']

② 通過 mapGetters 映射
默認根級別的映射 mapGetters([ 'xxx' ])
子模塊的映射 mapGetters('模塊名', ['xxx','xxx'...]) - 需要開啟命名空間

10.8 代碼演示

修改src/components/Son1.vue

<template><div class="box"><h2>Son1 子組件 使用原始方式獲取</h2><h4>$store.state.user: {{$store.state.user}}</h4><button @click="$store.commit('user/updateName', '李四')">修改名字</button><button @click="$store.dispatch('user/updateNameAsync', '王五')">1秒后修改</button><button @click="$store.commit('user/updateAge', 10)">年齡加10</button><h4>$store.getters["user/ageAddTen"]: {{$store.getters["user/ageAddTen"]}}</h4></div>
</template><script>
export default {computed: {},methods: {},mounted() {}}
</script><style lang="css" scoped>
.box{border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

在這里插入圖片描述

修改src/components/Son2.vue

<template><div class="box"><h2>Son2 子組件 使用輔助函數方式獲取</h2><h4>theme的值為: {{theme}}</h4><h4>desc的值為: {{desc }}</h4><button @click="updateTheme('light')">修改背景色</button><button @click="updateThemeAsync('blue')">一秒后修改背景色</button><h4>desc+theme的值為:{{ themeDesc }}</h4></div>
</template><script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
export default {computed: {...mapState('setting',["desc", "theme"]),...mapGetters('setting',["themeDesc"]),},methods: {...mapMutations('setting',["updateTheme"]),...mapActions('setting',["updateThemeAsync"]),}
};
</script><style lang="css" scoped>
.box {border: 3px solid #ccc;width: 400px;padding: 10px;margin: 20px;
}
h2 {margin-top: 10px;
}
</style>

運行結果
在這里插入圖片描述

總結

流程圖

在這里插入圖片描述

不使用分模塊的寫法

在這里插入圖片描述

使用分模塊寫法

在這里插入圖片描述

開啟嚴格模式

在Vuex的根節點文件src/store/index.js中開啟。

import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
import setting from './modules/setting'
Vue.use(Vuex)const store = new Vuex.Store({strict: true,state: { },mutations: {},actions: {},getters: {},modules: {user,setting}})
export default store

開啟命名空間

在子模塊src/store/modules/模塊.js中開啟。

const state = {}const mutations = {}const actions = {}const getters = {}export default {// 開啟命名空間namespaced: true,state,mutations,actions,getters
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/97664.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/97664.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/97664.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2025具身智能賽道觀察:技術、產業與視頻基礎設施

引言 2025 年&#xff0c;具身智能&#xff08;Embodied Intelligence&#xff09;毫無疑問已經成為全球資本追逐的“風口賽道”。從人形機器人、無人配送&#xff0c;到低空經濟和智能駕駛&#xff0c;幾乎所有與物理世界深度結合的領域&#xff0c;都被納入具身智能的廣義范…

【商業銀行風控模型(python版本,實操合集,附帶anaconda安裝教程,持續更新)】

Anaconda&#xff08;Python工具&#xff09;安裝1.Mac中安裝Anaconda2.點擊“Free Download”下載后&#xff0c;點擊“Skip registration”&#xff0c;跳過注冊環節。 3.conda list4.安裝完成Anaconda基本操作命令 # 查看當前虛擬環境下的所有包 conda list # 查看某個特定的…

FPGA DDR 地址映射-黃金法則

FPGA 中 DDR 控制器的地址映射順序&#xff08;Address Mapping Order&#xff09; 是優化設計速度&#xff08;帶寬和效率&#xff09; 的關鍵。簡單來說&#xff0c;地址映射順序決定了線性地址如何映射到 DDR 芯片內部的物理結構&#xff08;Bank、Row、Column&#xff09;。…

網絡安全設備監控指標

網絡安全設備監控指標 近日看到一篇設備情況匯報&#xff0c;內容寫得有些欠缺&#xff0c;因此我特意問了一下AI&#xff0c;整理了一下思路。以下是監控需要關注的性能指標。權當拋磚引玉。根據指標可以做監控&#xff0c;也可以做調研指標。 業務承載能力 吞吐量&#xff08…

JSP程序設計之JSP指令

1、JSP指令概念與分類 &#xff08;1&#xff09;概念 JSP指令相當于在編譯期間的命令&#xff0c;用來設置與整個JSP頁面相關的屬性&#xff0c;它并不直接產生任何可見的輸出&#xff0c;用來設置全局變量、聲明類、要實現的方法和輸出內容的類型等。在JSP文件被解析為Java…

Generative Art with p5.js: Creating Beauty from Code

Are you ready to make something truly beautiful with p5.js? Forget about boring bar charts and sales data—let’s create art that moves, breathes, and responds to your touch. We’re going to explore generative art, where code becomes your paintbrush and a…

Wi-Fi技術——網絡安全

一、數據幀的安全 1、無線網絡安全的發展 理論上無線電波范圍內的任何一個站點都可以監聽并登錄無線網絡&#xff0c;所有發送或接收的數據&#xff0c;都有可能被截取&#xff0c;因此無線網絡安全十分重要。 原始802.11的安全策略為WEP&#xff0c;其存在根本性的漏洞&#x…

Java提供高效后端支撐,Vue呈現直觀交互界面,共同打造的MES管理系統,含完整可運行源碼,實現生產計劃、執行、追溯一站式管理,提升制造執行效率

前言在當今競爭激烈的制造業環境中&#xff0c;企業面臨著提高生產效率、降低成本、保證產品質量以及快速響應市場變化等多重挑戰。制造執行系統&#xff08;MES&#xff0c;Manufacturing Execution System&#xff09;作為連接企業上層計劃管理系統&#xff08;如ERP&#xf…

【macOS】垃圾箱中文件無法清理的常規方法

【macOS】垃圾箱中文件無法清理的方法如果外接 SSD 移動盤上的垃圾文件無法刪除&#xff0c; 可能是由于文件系統格式不兼容、文件被占用、權限不足等原因導致的&#xff0c; 以下是一些常見的解決方法&#xff1a;檢查移動硬盤文件系統格式&#xff1a;如果移動硬盤是 NTFS 格…

鴻蒙ArkTS 核心篇-15-條件渲染(組件)

目錄 根據邏輯條件結果&#xff0c;渲染不同的 UI 內容 DevEco Studio代碼實戰 預覽效果 總結 根據邏輯條件結果&#xff0c;渲染不同的 UI 內容 DevEco Studio代碼實戰 let num: number 20Entry Component struct Index {build() {Column() {if (num 1) {Text(文本 1)} …

大模型微調顯存內存節約方法

大模型微調時節約顯存和內存是一個至關重要的話題&#xff0c;尤其是在消費級GPU&#xff08;如RTX 3090/4090&#xff09;或資源有限的云實例上。下面我將從顯存&#xff08;GPU Memory&#xff09; 和內存&#xff08;CPU Memory&#xff09; 兩個方面&#xff0c;為你系統地…

Linux筆記12——shell編程基礎-6

字符截取命令一、cut命令功能&#xff1a;用于從文件或標準輸入中提取指定字段或列語法&#xff1a;cut [選項] 文件名-f&#xff1a;列號&#xff0c;提取第幾列&#xff0c;默認識別制表符分割出來的列&#xff08;列號之間用,隔開&#xff09;-d&#xff1a;分隔符&#xff…

高效瀏覽器標簽頁管理:Chrome擴展開發完全指南

Hi&#xff0c;我是前端人類學&#xff08;之前叫布蘭妮甜&#xff09;&#xff01; 在信息過載的時代&#xff0c;瀏覽器標簽頁管理已成為提高工作效率的關鍵技能。本文將介紹如何開發一個功能完整的Chrome擴展&#xff0c;幫助用戶高效管理瀏覽器標簽頁&#xff0c;并探討其實…

從 WPF 到 Avalonia 的遷移系列實戰篇3:ResourceDictionary資源與樣式的差異與遷移技巧

從 WPF 到 Avalonia 的遷移系列實戰篇3:ResourceDictionary資源與樣式的差異與遷移技巧 我的GitHub倉庫Avalonia學習項目包含完整的Avalonia實踐案例與代碼對比。 我的gitcode倉庫是Avalonia學習項目。 文中主要示例代碼均可在倉庫中查看&#xff0c;涵蓋核心功能實現與優化方案…

基于Springboot的音樂媒體播放及周邊產品運營平臺(有報告)。Javaee項目,springboot項目。

演示視頻&#xff1a; 基于Springboot的音樂媒體播放及周邊產品運營平臺&#xff08;有報告&#xff09;。Javaee項目&#xff0c;springboot項目。項目介紹&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09…

【項目思維】嵌入式產業鏈與技術生態

這篇文章深入解析嵌入式產業鏈與技術生態上下游關系&#xff0c;輔助建立嵌入式工程師職業發展認知。嵌入式行業并不是“寫單片機程序”那么簡單&#xff0c;而是一個 從芯片設計到系統集成再到最終產品落地 的復雜生態鏈。理解上下游價值鏈&#xff0c;有助于你成為系統型工程…

機器學習(講解)

一、引言&#xff1a;什么是監督學習&#xff1f;監督學習&#xff08;Supervised Learning&#xff09;是機器學習中最基礎且應用最廣泛的范式之一。其核心思想是利用已標記的數據&#xff08;即輸入-輸出對&#xff09;訓練模型&#xff0c;使其能夠對新的、未標記的數據進行…

使用 Bright Data Web Scraper API + Python 高效抓取 Glassdoor 數據:從配置到結構化輸出全流程實戰

使用 Bright Data Web Scraper API Python 高效抓取 Glassdoor 數據&#xff1a;從配置到結構化輸出全流程實戰 摘要 本文詳細介紹了如何使用 Bright Data 的 Web Scraper API 搭配 Python&#xff0c;實現對 Glassdoor 平臺信息的高效抓取。通過 API 請求構建器、反爬機制集成…

Burgan Bank Türkiye 如何借助 Elastic 改造可觀測性和安全性

作者&#xff1a;來自 Elastic Jon Ashley, Ido Friedman, Burak Dz Burgan Bank Trkiye Burgan Bank K.P.S.C. 是科威特項目公司 (KIPCO) 集團的子公司&#xff0c;成立于 1977 年&#xff0c;是中東和北非 (MENA) 地區最大的控股集團和重要銀行集團之一。 該銀行作為客戶的解…

LeetCode 165. 比較版本號 - 優雅Java解決方案

文章目錄LeetCode 165. 比較版本號 - 優雅Java解決方案題目描述示例分析示例 1示例 2示例 3算法思路Java實現方案方案一&#xff1a;雙指針法&#xff08;推薦&#xff09;方案二&#xff1a;優化的單次遍歷法可視化執行過程示例&#xff1a;compareVersion("1.2", &…