Rumah >hujung hadapan web >View.js >Ambil Vuex sebagai contoh untuk membongkar misteri pengurusan negeri

Ambil Vuex sebagai contoh untuk membongkar misteri pengurusan negeri

藏色散人
藏色散人ke hadapan
2021-12-16 15:46:081883semak imbas

Menggunakan Vuex sebagai panduan , sepintas lalu gambaran keseluruhan pengurusan negeri

Seperti yang kita sedia maklum, Vuex ialah penyelesaian pengurusan negeri rasmi Vue.

Penggunaan dan API Vuex tidak sukar, dan pengenalan laman web rasmi juga ringkas dan jelas. Terima kasih kepada ini, sangat mudah untuk menyepadukan Vuex dengan cepat ke dalam projek anda. Walau bagaimanapun, kerana penggunaannya yang fleksibel, ramai pelajar agak keliru dalam reka bentuk dan penggunaan Vuex.

Malah, sebelum menggunakannya, kita juga boleh berhenti seketika dan memikirkan beberapa soalan:

  • Apakah itu pengurusan negeri?
  • Mengapa saya perlu menggunakan Vuex?
  • Bagaimana untuk mengagihkan keadaan dalaman komponen dan keadaan Vuex?
  • Apakah masalah yang mungkin timbul dengan menggunakan Vuex?

Jika anda samar-samar tentang soalan-soalan ini, maka tahniah, artikel ini mungkin yang anda perlukan.

Sila sertai saya di bawah untuk mendedahkan misteri pengurusan negeri bermula dari asal, menggunakan Vuex sebagai contoh.

Pratonton Garis Besar

Kandungan yang diperkenalkan dalam artikel ini merangkumi aspek berikut:

  • Kelahiran negeri dan komponen
  • Adakah pengurusan negeri memerlukan untuk diuruskan?
  • Sumber data tunggal
  • Kaedah kemas kini status
  • Kemas kini tak segerak?
  • Kemodulan Negeri
  • Slot Pemodulatan
  • Langkah Seterusnya

Kelahiran Negara dan Komponen

Sejak Tiga Sejak kelahiran rangka kerja besar, dua keupayaan yang mereka kongsikan telah melanda Jquery sepenuhnya. Kedua-dua keupayaan ini ialah:

  1. Paparan dipacu data
  2. Pengkomponenan

Pandangan dipacu data membolehkan kami mengucapkan selamat tinggal kepada era apabila kami hanya boleh bergantung pada memanipulasi DOM untuk mengemas kini halaman. Kami tidak perlu lagi mencari DOM melalui lapisan find dan kemudian mengubah suai sifat dan kandungannya setiap kali kami mengemas kini halaman Kami boleh melakukan perkara ini dengan memanipulasi data.

Sudah tentu, di mata bahagian hadapan kami, data pada asasnya boleh difahami sebagai 变量 yang menyimpan pelbagai jenis data. Selepas konsep 数据驱动 muncul, beberapa pembolehubah turut diberi makna yang istimewa.

Pertama sekali, ia adalah pembolehubah biasa, yang tidak berbeza dengan era JQ dan hanya digunakan untuk menyimpan data. Selain itu, terdapat jenis pembolehubah yang mempunyai kesan responsif Pembolehubah ini terikat pada paparan Apabila pembolehubah berubah, pandangan yang terikat pada pembolehubah ini juga akan mencetuskan kemas kini yang sepadan pembolehubah.

Apa yang dipanggil paparan dipacu data, secara tegasnya, bermakna pembolehubah keadaan memacu paparan. Dengan populariti Vue dan React, tumpuan pembangun bahagian hadapan telah beralih secara beransur-ansur daripada mengendalikan DOM kepada data pengendalian, dan pembolehubah keadaan telah menjadi teras.

Nyatakan pembolehubah, kini semua orang nampaknya lebih suka memanggilnya

Negeri. Kita sering bercakap tentang pengurusan negeri dan negeri Sebenarnya, negeri ini merujuk kepada pembolehubah negeri. Keadaan yang dinyatakan di bawah juga merujuk kepada pembolehubah keadaan.

Selepas status datang, komponen juga datang.

Dalam era JQ, halaman muka hadapan hanyalah html Tiada konsep "komponen" untuk menggunakan semula bahagian biasa halaman secara elegan. Nasib baik, tiga rangka kerja utama telah menghasilkan reka bentuk komponen yang sangat matang. Ia adalah mudah untuk mengekstrak serpihan DOM sebagai komponen, dan komponen itu boleh mengekalkan keadaannya sendiri secara dalaman, menjadikannya lebih bebas.

Ciri penting komponen ialah keadaan dalaman ini diasingkan dari luar. Komponen induk tidak boleh mengakses keadaan dalaman komponen anak, tetapi komponen anak boleh mengakses keadaan (Props) yang diluluskan oleh komponen induk dan bertindak balas secara automatik mengikut perubahan.

Ciri ini boleh difahami sebagai keadaan yang dimodulasi. Kelebihan ini ialah tidak perlu mempertimbangkan bahawa keadaan tetapan semasa akan mempengaruhi komponen lain. Sudah tentu, adalah tidak realistik untuk mengasingkan sepenuhnya status komponen Sudah pasti akan terdapat keperluan untuk berbilang komponen untuk berkongsi status .

Skim status kongsi di atas biasanya tiada masalah dan juga merupakan amalan terbaik yang disyorkan secara rasmi.

Tetapi jika halaman anda rumit, anda akan mendapati ia masih tidak mencukupi. Contohnya:

    Hierarki komponen terlalu mendalam dan perlu berkongsi keadaan Pada masa ini, keadaan perlu dilalui lapisan demi lapisan.
  • Komponen kanak-kanak mengemas kini keadaan, yang mungkin mempunyai berbilang komponen induk dan dikongsi oleh komponen adik-beradik, menjadikannya sukar untuk dilaksanakan.
Dalam kes ini, teruskan gunakan kaedah "

Ekstrak keadaan kepada komponen induk " dan anda akan mendapati ia sangat rumit. Dan apabila bilangan komponen meningkat dan tahap bersarang semakin dalam, kerumitan menjadi lebih tinggi dan lebih tinggi. Oleh kerana terdapat banyak keadaan yang berkaitan dan pemindahan kompleks, adalah mudah untuk masalah seperti komponen dikemas kini secara tidak dapat dijelaskan atau komponen tidak dikemas kini dan penyelesaian masalah yang tidak normal menjadi sukar.

Memandangkan perkara ini, kami memerlukan penyelesaian yang lebih elegan untuk menangani situasi yang kompleks ini.

Perlukan pengurusan status?

Seperti yang kami nyatakan dalam bahagian sebelumnya, apabila halaman menjadi lebih kompleks, kami telah menghadapi masalah sukar dalam pelaksanaan keadaan kongsi merentas komponen.

Jadi adakah penyelesaiannya? Sudah tentu ada, dan berkat usaha pemimpin masyarakat, terdapat lebih daripada satu rancangan. Tetapi semua penyelesaian ini mempunyai nama yang sama, iaitu apa yang kami bincangkan dengan sangat mendalam dua tahun lalu - Pengurusan Negeri.

Pengurusan negeri sebenarnya boleh difahami sebagai pengurusan negeri global Keadaan di sini berbeza daripada keadaan di dalam komponen, dan kemudian dipadankan dengan keperluan dalam beberapa cara. Komponen negeri ini dikaitkan.

Pengurusan negeri mempunyai rancangan pelaksanaannya sendiri. Vue mempunyai Vuex, React mempunyai Redux, Mobx, dan sudah tentu terdapat penyelesaian lain. Tetapi mereka semua menyelesaikan masalah yang sama, iaitu masalah perkongsian keadaan merentas komponen.

Saya masih ingat bahawa dalam dua tahun yang lalu, kerana populariti konsep "pengurusan negeri", ia seolah-olah telah menjadi bahagian yang sangat diperlukan dalam pembangunan aplikasi. Mengambil Vue sebagai contoh, mencipta projek pasti akan memperkenalkan Vuex untuk pengurusan negeri. Tetapi ramai orang tidak tahu mengapa, bila untuk digunakan, dan bagaimana untuk menggunakan pengurusan negeri, dan mereka hanya mengikut trend secara membabi buta Akibatnya, terdapat banyak contoh penyalahgunaan pengurusan negeri.

Melihat ini, anda harus tahu bahawa pengurusan negeri tidak diperlukan. Mengapa ia muncul dan masalah yang diselesaikannya pada dasarnya dijelaskan di atas. Jika anda tidak faham, jeda dan baca semula dari awal. Jangan fikir bahawa latar belakang penyelesaian teknikal adalah tidak penting Jika anda tidak memahami masalah yang direka untuk diselesaikan, maka anda tidak akan dapat memainkan peranannya.

Pengarang Redux mempunyai pepatah terkenal: Jika anda tidak tahu sama ada anda memerlukan Redux (pengurusan negeri), maka anda tidak memerlukannya.

Baiklah, jika anda menggunakan pengurusan negeri, atau perlu menggunakan pengurusan negeri untuk membantu anda menyelesaikan masalah, mari teruskan membaca.

Vuex

Vue digunakan secara meluas di China, terutamanya untuk pasukan bersaiz kecil dan sederhana, jadi penyelesaian pengurusan negeri pertama yang kebanyakan orang hubungi adalah Vuex.

Jadi bagaimanakah Vuex menyelesaikan masalah perkongsian keadaan merentas komponen? Mari kita terokai bersama-sama.

Buat kedai

Seperti yang kami nyatakan di atas, untuk status perkongsian komponen umum, pengesyoran rasmi adalah untuk "Mengekstrak status kepada komponen induk terdekat ". Vuex mengambil langkah lebih jauh dan mengekstrak semua keadaan ke komponen akar supaya mana-mana komponen boleh mengaksesnya.

Mungkin anda akan bertanya: Bukankah ini mendedahkan status kepada seluruh dunia? Bukankah ia akan menghapuskan sepenuhnya kelebihan modulariti?

Bukan begitu. Tujuan utama Vuex melakukan ini adalah untuk membenarkan semua komponen mengakses keadaan ini dan mengelakkan sepenuhnya situasi di mana keadaan subkomponen tidak boleh diakses. Vuex meletakkan semua data keadaan pada satu objek, mengikut prinsip Sumber Data Tunggal. Tetapi ini tidak bermakna bahawa keadaan itu disusun Vuex melaksanakan penyelesaian modularnya sendiri pada pokok keadaan tunggal ini.

Jangan risau, mari kita pergi langkah demi langkah dan lihat cara menggunakan Vuex dahulu.

Vuex wujud sebagai pemalam untuk Vue Mula-mula pasang dengan npm:

$ npm install --save vuex

Selepas pemasangan, kami mencipta folder src/store baharu dan meletakkan semua kod berkaitan Vuex di sini. .

Buat index.js baharu dan tulis kod berikut. Fungsi utama kod ini adalah untuk memuatkan pemalam Vuex menggunakan kaedah Vue.use, dan kemudian mengeksport contoh Vuex.Store yang dikonfigurasikan.

import Vue from 'vue'
import Vuex from 'vuex'
// 安装插件
Vue.use(Vuex)

export default new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  modules: {}
})

Instance yang dieksport di atas biasanya dipanggil store. Stor mengandungi keadaan tersimpan (state) dan fungsi yang mengubah suai keadaan (mutation Semua keadaan dan operasi yang berkaitan ditakrifkan di sini.

Langkah terakhir ialah melekapkan contoh kedai yang dieksport di atas ke Vue dalam fail masukan:

import store from './store'

new Vue({
  el: '#app',
  store: store
})

Nota: Langkah pemasangan ini tidak perlu. Tujuan langkah pemasangan ini hanyalah untuk memudahkan akses contoh kedai kami yang dieksport melalui this.$store dalam komponen .vue. Jika ia tidak dipasang, ia adalah sama seperti import langsung.

Sumber data tunggal (keadaan)

Dalam langkah sebelumnya, kami menggunakan pembina Vuex.Store untuk mencipta tika kedai Setiap orang sekurang-kurangnya tahu cara menggunakan Vuex. Dalam langkah ini, mari kita lihat konfigurasi khusus pembina Vuex.Store.

Yang pertama ialah konfigurasi state, yang nilainya ialah objek yang digunakan untuk menyimpan keadaan. Vuex menggunakan prinsip 单一状态树 untuk meletakkan semua keadaan pada objek ini untuk memudahkan lokasi keadaan seterusnya dan penyahpepijatan.

Sebagai contoh, kami mempunyai keadaan awal app_version yang mewakili versi, seperti berikut:

new Vuex.Store({
  state: {
    app_version: '0.1.1'
  }
}

Sekarang untuk mendapatkannya dalam komponen, anda boleh melakukan ini:

this.$store.state.app_version

Tetapi Ini bukan satu-satunya cara untuk mendapatkannya, ia juga boleh seperti ini:

import store from '@/store' // @ 表示 src 目录
store.state.app_version

Mengapa kita harus menekankan perkara ini? Sebab ramai kawan beranggapan Vuex hanya boleh dikendalikan melalui this.$store. Apabila ia datang kepada bukan komponen, sebagai contoh, jika anda ingin menetapkan keadaan Vuex tertentu dalam fungsi permintaan, anda tidak tahu apa yang perlu dilakukan.

Malah, terdapat cara yang lebih elegan untuk mendapatkan status dalam komponen, seperti fungsi mapState, yang memudahkan untuk mendapatkan berbilang keadaan.

import { mapState } from 'vuex'

export default {
  computed: {
    ... // 其他计算属性
    ...mapState({
      version: state => state.app_version
    })
  }
}

状态更新方式(mutation)

Vuex 中的状态与组件中的状态不同,不能直接用 state.app_version='xx' 这种方式修改。Vuex 规定修改状态的唯一方法是提交 mutation

Mutation 是一个函数,第一个参数为 state,它的作用就是更改 state 的状态。

下面定义一个名叫 increment 的 mutation,在函数内更新 count 这个状态:

new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment(state, count) {
      // 变更状态
      state.count += count
    }
  }
})

然后在 .vue 组件中触发 increment

this.$store.commit('increment', 2)

这样绑定了 count 的视图就会自动更新。

同步更新

虽然 mutation 是更新状态的唯一方式,但实际上它还有一个限制:必须是同步更新

为什么必须是同步更新?因为在开发过程中,我们常常会追踪状态的变化。常用的手段就是在浏览器控制台中调试。而在 mutation 中使用异步更新状态,虽然也会使状态正常更新,但是会导致开发者工具有时无法追踪到状态的变化,调试起来就会很困难。

再有 Vuex 给 mutation 的定位就是更改状态,只是更改状态,别的不要参与。所谓专人干专事儿,这样也帮助我们避免把更改状态和自己的业务逻辑混起来,同时也规范了函数功能。

那如果确实需要异步更新,该怎么办呢?

异步更新

异步更新状态是一个非常常见的场景,比如接口请求回来的数据要存储,那就是异步更新。

Vuex 提供了 action 用于异步更新状态。与 mutation 不同的是,action 不直接更新状态,而是通过触发 mutation 间接更新状态。因此即便使用 action 也不违背 “修改状态的唯一方法是提交 mutation” 的原则。

Action 允许在实际更新状态前做一些副作用的操作,比如上面说的异步,还有数据处理,按条件提交不同的 mutation 等等。看一个例子:

new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    add(state) {
      state.count++
    },
    reduce(state) {
      state.count--
    }
  },
  actions: {
    increment(context, data) {
      axios.get('**').then(res => {
        if (data.iscan) {
          context.commit('add')
        } else {
          context.commit('reduce')
        }
      })
    }
  }
})

在组件中触发 action:

this.$store.dispatch('increment', { iscan: true })

这些就是 action 的使用方法。其实 action 最主要的作用就是请求接口,拿到需要的数据,然后触发 mutation 修改状态。

其实这一步在组件中也可以实现。我看过一些方案,常见的是在组件内写一个请求方法,当请求成功,直接通过 this.$store.commit 方法触发 mutation 来更新状态,完全用不到 action。

难道 action 可有可无吗?

也不是,在特定场景下确实需要 action 的,这个会在下一篇说。

状态模块化(module)

前面讲过,Vuex 是单一状态树,所有状态存放在一个对象上。同时 Vuex 有自己的模块化方案
,可以避免状态堆砌到一起,变的臃肿。

Vuex 允许我们将 store 分割成模块(module),每个模块拥有自己的 state、mutation、action。虽然状态注册在根组件,但是支持模块分割,相当于做到了与页面组件平级的“状态组件”。

为了区分,我们将被分割的模块称为子模块,暴露在全局的称为全局模块

我们来看基础用法:

new Vuex.Store({
  modules: {
    user: {
      state: {
        uname: 'ruims'
      },
      mutation: {
        setName(state, name) {
          state.name = name
        }
      }
    }
  }
})

上面定义了 user 模块,包含了一个 state 和一个 mutation。在组件中使用方法如下:

// 访问状态
this.$store.state.user.uname
// 更新状态
this.$store.commit('setName')

大家发现了,访问子模块的 state 要通过 this.$store.state.[模块名称] 这种方式去访问,触发 mutation 则与全局模块一样,没有区别。

action 与 mutation 原理一致,不细说。

命名空间

上面说到,子模块触发 mutation 和 action 与全局模块一致,那么假设全局模块和子模块中都有一个名为 setName 的 mutation。在组件中触发,哪个 mutation 会执行呢?

经过试验,都会执行。官方的说法是:为了多个模块能够对同一 mutation 或 action 作出响应。

其实官方做的这个兼容,我一直没遇到实际的应用场景,反而因为同名 mutation 导致误触发带来了不少的麻烦。可能官方也意识到了这个问题,索引后来也为 mutation 和 action 做了模块处理方案。

这个方案,就是命名空间。

命名空间也很简单,在子模块中加一个 namespaced: true 的配置即可开启,如:

new Vuex.Store({
  modules: {
    user: {
      namespaced: true,
      state: {}
    }
  }
})

开启命名空间后,触发 mutation 就变成了:

this.$store.commit('user/setName')

可见提交参数由 '[mutation]' 变成了 '[模块名称]/[mutation]'

模块化的槽点

上面我们介绍了 Vuex 的模块化方案,将单一状态树 store 分割成多个 module,各自负责本模块状态的存储和更新。

模块化是必要的,但是这个模块的方案,用起来总觉得有点别扭

比如,总体的设计是将 store 先分模块,模块下在包含 state,mutation,action。

那么按照正常理解,访问 user 模块下 state 应该是这样的:

this.$store.user.state.uname

但是实际 API 却是这样的:

this.$store.state.user.uname

这个 API 仿佛是在 state 中又各自分了模块。我没看过源码,但从使用体验上来说,这是别扭一。

除 state 外,mutation,action 默认注册在全局的设计,也很别扭

首先,官方说的多个模块对同一 mutation 或 action 作出响应,这个功能暂无找到应用场景。并且未配 namespace 时还要保证命名唯一,否则会导致误触发。

其次,用 namespace 后,触发 mutation 是这样的:

this.$store.commit('user/setName')

这个明显是将参数单独处理了,为什么不是这样:

this.$store.user.commit('setName')

总体感受就是 Vuex 模块化做的还不够彻底。

为什么吐槽

上面说的槽点,并不是为了吐槽而吐槽。主要是感觉还有优化空间。

比如 this.$store.commit 函数可以触发任何 mutation 来更改状态。如果一个组件复杂,需要操作多个子模块的状态,那么就很难快速的找出当前组件操作了哪些子模块,当然也不好做权限规定。

我希望的是,比如在 A 组件要用到 b, c 两个子模块的状态,不允许操作其他子模块,那么就可以先将要用到模块导入,比如这样写:

import { a, b } from this.$store
export default {
  methods: {
    test() {
      alert(a.state.uname) // 访问状态
      a.commit('setName')// 修改状态
    }
  }
}

这样按照模块导入,查询和使用都比较清晰。

下一步

前面我们详细介绍了状态管理的背景以及 Vuex 的使用,分享了关于官方 API 的思考。相信看到这里,你已经对状态管理和 Vuex 有了更深刻的认识和理解。

然而本篇我们只介绍了 Vuex 这一个方案,状态管理的其他方案,以及上面我们的吐槽点,能不能找到更优的实现方法,这些都等着我们去尝试。

下一篇文章我们继续深挖状态管理,对比 Vuex 和 React,Fluter 在状态管理实现上的差异,然后在 Vue 上集成 Mobx,打造我们优雅的应用。

Atas ialah kandungan terperinci Ambil Vuex sebagai contoh untuk membongkar misteri pengurusan negeri. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:segmentfault.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam