1. 程式人生 > 其它 >Java基礎10:三元運算子及小結

Java基礎10:三元運算子及小結

1. 介紹

1.1. 元件化開發

在現代 Web 開發複雜多變的需求驅動之下,元件化開發已然成為了事實上的標準。

元件化開發為我們帶來了:

  • 更快的開發效率
  • 更好的可維護性

1.2. 元件內的狀態管理流程

每個元件都有自己的狀態、檢視和行為等組成部分。

new Vue({
 // state
 data() {
  return {
   count: 0,
  };
 },
 // view
 template: `
        <div>{{ count }}</div>
        `,
 // actions
 methods: {
  increment() {
   this.count++;
  },
 },
});
  • state,驅動應用的資料來源;
  • view,以宣告方式將 state 對映到檢視;
  • actions,響應在 view 上的使用者輸入導致的狀態變化

以下是一個表示“單向資料流”理念的簡單示意:

1.3. 元件通訊

然而大多數場景下的元件都並不是獨立存在的,而是相互協作共同構成了一個複雜的業務功能。在 Vue
中為不同的元件關係提供了不同的通訊規則。

  • 父子關係
  • 非父子
  • 。。。

1.3.1. 父傳子:Props Down

<blog-post title="My journey with Vue"></blog-post>
Vue.component("blog-post", {
 props: ["title"],
 template: "<h3>{{ title }}</h3>",
});

1.3.2. 子傳父:Events Up

在子元件中使用 $emit 釋出一個自定義事件:

<button v-on:click="$emit('enlarge-text')">
 Enlarge text
</button>

在使用這個元件的時候,使用 v-on 監聽這個自定義事件

<blog-post ... v-on:enlarge-text="postFontSize += 0.1"></blog-post>

1.3.3. 通過 ref 獲取子元件

在使用元件的時候,新增 ref 屬性:

<blog-post title="My journey with Vue" ref="post"></blog-post>

然後使用 $refs 訪問:

this.$refs.post;

1.3.4. 非父子:Event Bus

我們可以使用一個非常簡單的 Event Bus 來解決這個問題:

event-bus.js :

export default new Vue();

然後在需要通訊的兩端:

使用 $on訂閱:

// 沒有引數
bus.$on("自定義事件名稱", () => {
 // 執行操作
});
// 有引數
bus.$on("自定義事件名稱", (data) => {
 // 執行操作
});

使用$emit釋出:

// 沒有自定義傳參
bus.$emit("自定義事件名稱");

// 有自定義傳參
bus.$emit("自定義事件名稱", 資料);

1.4. 多個元件狀態共享

但是,當我們的應用遇到多個元件共享狀態時:

  • 多個檢視依賴於同一狀態
  • 來自不同檢視的行為需要變更同一狀態

最典型的場景就是購物車

對於問題一,傳參的方法對於多層巢狀的元件將會非常繁瑣,並且對於兄弟元件間的狀態傳遞無能為
力。

對於問題二,我們經常會採用父子元件直接引用或者通過事件來變更和同步狀態的多份拷貝。以上的這
些模式非常脆弱,通常會導致無法維護的程式碼。

因此,我們為什麼不把元件的共享狀態抽取出來,以一個全域性單例模式管理呢?在這種模式下,我們的
元件樹構成了一個巨大的“檢視”,不管在樹的哪個位置,任何元件都能獲取狀態或者觸發行為!

通過定義和隔離狀態管理中的各種概念並通過強制規則維持檢視和狀態間的獨立性,我們的程式碼將會變
得更結構化且易維護。

1.5. 什麼是 Vuex

官方文件:Vuex是一個專為 Vue.js應用程式開發的狀態管理模式。它採用集中式儲存管理應用
的所有元件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。Vuex 也整合到 Vue
的官方除錯工具 devtools extension,提供了諸如零配置的 time-travel 除錯、狀態快照匯入匯出
等高階除錯功能。

  • Vue 是專門為Vue.js 設計的狀態管理庫
  • 它採用集中式的方式儲存需要共享的資料
  • 從使用角度,它就是一個 JavaScript 庫
  • 它的作用是進行狀態管理,解決複雜元件通訊,資料貢獻

1.6. 什麼情況下使用 Vuex

官方文件:
Vuex 可以幫助我們管理共享狀態,並附帶了更多的概念和框架。這需要對短期和長期效益進行權
衡。
如果您不打算開發大型單頁應用,使用Vuex 可能是繁瑣冗餘的。確實是如此——如果您的應用
夠簡單,您最好不要使用Vuex。一個簡單的 store 模式就足夠您所需了。但是,如果您需要構建
一箇中大型單頁應用,您很可能會考慮如何更好地在元件外部管理狀態,Vuex 將會成為自然而然
的選擇。引用 Redux的作者 Dan Abramov的話說就是:Flux 架構就像眼鏡:您自會知道什麼時
候需要它。

當你的應用中具有以下需求場景的時候:

  • 多個檢視依賴於同一狀態
  • 來自不同檢視的行為需要變更同一狀態

建議符合這種場景的業務使用 Vuex來進行資料管理,例如非常典型的場景:購物車

注意:Vuex 不要濫用,不符合以上需求的業務不要使用,反而會讓你的應用變得更麻煩

2. 準備

實現一個類似於購物車的元件案例

1、使用 VueCLI 建立一個練習專案:

vue create vuex-demo cd vuex-demo npm run serve

2、準備兩個元件

Foo.vue 和 Bar.vue

3、最後在 App.vue 中載入使用 Foo 和 Bar

最終達到上圖效果

3. 安裝 Vuex

官方文件:https://vuex.vuejs.org/zh/installation.html

最方便的方式就是使用 npm:

# 或者 yarn add vuex
 npm install vuex

4. 配置 Vuex

1、在專案中新建store/index.js

import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
/**
 * 建立一個 Vuex 容器例項,用來在元件的外部管理共享的資料狀態
 */
const store = new Vuex.Store({
 /**
  * 類似於元件中的 data
  */
 state: {
  count: 0,
 },
});
export default store;

2、在 main.jsstore註冊到 Vue根例項

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

5. State

目標:
知道什麼是 State
掌握如何定義 State
掌握如何在元件中訪問 State 資料

容器中的 state 就好比元件的 data,用來儲存共享資料:

  • 容器中的資料是共享的,任何元件都可以訪問
  • 容器中的資料也是響應式的,資料改變也會驅動檢視更新

在元件中訪問容器中的資料,可以通過以下幾種方式。

在元件模板中直接通過 $store 訪問容器資料:

<div>
 <p>{{ $store.state.count }}</p>
</div>

在元件 JavaScript 中訪問容器資料需要加 this :

methods: {
    onClick () {
        console.log(this.$store.state.count)
    }
}

如果在元件中多次使用到容器資料,可以將其封裝到一個計算屬性中:

computed: {
    count () {
        return this.$store.state.count
    }
}

然後就像使用訪問自己的資料一樣來訪問容器中的資料

<div>
 <p>{{ count }}</p>
</div>

6. 在除錯工具中除錯 Vuex 容器資料

也可以通過除錯工具檢視 Vuex 容器中的資料:

7. Mutation

目標:

  • 瞭解 Mutation 的作用是什麼
  • 掌握如何定義 Mutation
  • 掌握如何呼叫 Mutation

更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。Vuex 中的 mutation 非常類似於事件:每
個 mutation 都有一個字串的 事件型別 (type) 和 一個 回撥函式 (handler)。這個回撥函式就是我們
實際進行狀態更改的地方,並且它會接受 state 作為第一個引數:

const store = new Vuex.Store({
 state: {
  count: 1,
 },
 mutations: {
  increment(state) {
   // 變更狀態
   state.count++;
  },
 },
});

然後在元件中呼叫 mutation:

<template>
 <div class="com">
  <h2>Bar 元件</h2>
  <p>{{ $store.state.count }}</p>
  <!-- 如果是在 JS 中,則 this.$store.commit('increment') -->
  <button @click="$store.commit('increment')">-</button>
 </div>
</template>

mutation 函式也可以自定義傳參:

// ...
mutations: {
    increment (state, n) {
        state.count += n
    }
}

store.commit("increment", 10);

注意:mutation 只能傳遞 1 個自定義引數

如果需要傳遞多個引數,就放到一個物件中:

// ...
mutations: {
    increment (state, payload) {
        console.log(payload) // { n: 10, m: 20 }
        state.count += payload.n
    }
}
store.commit("increment", {
 n: 10,
 m: 20,
});

提交 mutation 的另一種方式是直接使用包含 type屬性的物件:

store.commit({
 type: "increment",
 amount: 10,
});

當使用物件風格的提交方式,整個物件都作為載荷傳給 mutation 函式,因此處理函式保持不變:

mutations: {
    increment (state, payload) {
        state.count += payload.amount
    }
}

總結:

  • 修改容器的 state 務必使用 mutation 函式,因為只有 mutation 函式中修改 state 資料才會和除錯工具正常工作。
  • mutation 函式的第 1 個引數是 state 物件
  • mutation 函式也可以自定義傳參
  • 注意:不要在 mutation 中執行非同步操作修改 state 、除錯工具會出現問題。

9.Action

目標:

  • 瞭解 Action 的作用是什麼
  • 掌握如何定義 Action
  • 掌握如何呼叫 Action

Action 類似於 mutation,不同在於:

  • Action 提交的是 mutation,而不是直接變更狀態。
  • Action 可以包含任意非同步操作。

9.1. 定義 Action

讓我們來註冊一個簡單的 action:

const store = new Vuex.Store({
 state: {
  count: 0,
 },
 mutations: {
  increment(state) {
   state.count++;
  },
 },
 actions: {
  increment(context) {
   // 執行非同步操作
   setTimeout(() => {
    // 提交 mutation 更新 state
    context.commit("increment");
   }, 1000);
  },
 },
});

Action 函式接受一個與 store 例項具有相同方法和屬性的 context 物件,因此你可以呼叫
context.commit 提交一個 mutation。
Action 通過store.dispatch方法觸發:

store.dispatch("increment");

例如我在元件中:

<button @click="$store.dispatch('increment')">分發 Action</button>

Actions 和 Mutation 一樣,也支援自定義傳參:

<!-- 只有一個引數 -->
<button @click="$store.dispatch('increment', 10)">分發 Action</button>
<!-- 多個引數放到一個物件中 -->
<button @click="$store.dispatch('increment', { n: 10, m: 20 })">
 分發 Action
</button>

總結:

  • action 中非同步操作結束以後,提交 mutation 來修改 state
  • 注意:也不要在 action 中直接修改 state,永遠通過 mutation 來修改 state
  • action 函式的第 1 個引數是容器物件
  • action 也可以像 mutation 函式一樣自定義傳參

10. Vuex 狀態管理流程

10.1. 同步操作

  • 元件通過 Commit 呼叫 Mutations 中的方法
  • Mutations 執行內部邏輯修改 State 資料 ,同時在除錯工具 Devtools 上顯示對應變化內容
  • State 變化影響元件檢視更新

10.2 非同步操作

  • 元件通過 Dispatch 呼叫 Actions 中的方法
  • Actions 中的方法通過 Commit 呼叫 Mutations 中的方法
  • Mutations 執行內部邏輯修改 State 資料 ,同時在除錯工具 Devtools 上顯示對應變化內容
  • State 變化影響元件檢視更新

注意點:

  • 不要在 action 中直接修改 state,除錯工具工作有問題
  • 也不要在 mutation 中執行非同步操作修改 state,除錯工具工作有問題
  • 只有 mutation 中修改 state 才能反應到除錯工具中