日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > vue >内容正文

vue

前端入门之(vuex源码解析一)

發(fā)布時(shí)間:2023/12/29 vue 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 前端入门之(vuex源码解析一) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言: 這兩天聽到最多的就是“假疫苗“事件了,唉唉~~ 真的是為了利益可以不管不顧一切啊,這可能也是當(dāng)今社會(huì)的一個(gè)現(xiàn)象,悲哀!! 說是有臺(tái)風(fēng)啥的,在家一個(gè)人默默地待了兩天,一個(gè)人的時(shí)候總喜歡胡思亂想,甚至?xí)ㄉ弦徽斓臅r(shí)間思考完整個(gè)人生,有時(shí)候真希望自己能夠活得天真或者自私點(diǎn),這樣就不會(huì)有太多煩惱了.

bb了一會(huì)進(jìn)入今天的主題哈,入坑前端也有一段時(shí)間了,從android的(data-binding、eventbus、rxjava)、rn的redux、然后vue的vuex,以前也就是用用,沒太大感覺,每個(gè)框架都是大同小異,最終的目的也就是是全局狀態(tài)的管理,redux跟android的data-binding啥的小伙伴有時(shí)間自己去研究哈,正好最近一直在接觸vue,所以就從vuex開刀了~~

先附上vuex的官網(wǎng)地址和github地址:
https://vuex.vuejs.org/zh/installation.html
https://github.com/vuejs/vuex

至于vuex是什么?然后vuex的基本用法?我就不說了哈,官網(wǎng)比我說的好~~ 哈哈哈

我們用vue-cli創(chuàng)建一個(gè)簡(jiǎn)單的vue工程:

vue init webpack VuexDemo

然后安裝vuex

yarn add vuex

最后修改工程的HelloWorld.vue,然后添加按鈕+-:

<template><div class="hello"><div class="opt-container"><div class="opt opt-increase" @click="increase">+</div><span class="opt">{{count}}</span><div class="opt opt-decrease" @click="decrease">-</div></div></div> </template><script>export default {name: 'HelloWorld',data() {return {count: 0}},methods: {increase() {this.count++;},decrease() {this.count--;}}} </script><!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped>.opt-container {font-size: 0px;}.opt {display: inline-block;text-align: center;height: 40px;width: 40px;border-radius: 20px;background-color: #efefef;line-height: 40px;user-select: none;font-size: 20px;margin: 0 10px;} </style>

最后運(yùn)行工程:

哈哈~走到這一步,想必只要接觸過vue的童鞋都沒問題,好啦~~ 我們現(xiàn)在就把我們的count變量抽取到vuex里面去.小伙伴跟著我一起往下走哈~~

首先我們創(chuàng)建一個(gè)store文件夾,然后返回store對(duì)象:

/*** @author YASIN* @version [React-Native Ocj V01, 2018/7/22]* @date 17/2/23* @description index*/ import Vue from 'vue'; import Vuex from 'vuex';Vue.use(Vuex); let state = {count: 0 }; const actions = {increase({commit}) {commit('increase');},decrease({commit}) {commit('decrease');} }; const mutations = {increase(state) {this.state.count++;},decrease(state) {this.state.count--;} }; export default new Vuex.Store({state,actions,mutations });

然后修改我們的main.js文件,把store引入到vue組件中:

// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import router from './router' import store from './store'Vue.config.productionTip = false/* eslint-disable no-new */ new Vue({el: '#app',router,store,components: {App},template: '<App/>' })

最后我們?cè)谖覀兊慕M件中把count跟store中的count綁定,然后添加increase跟decrease方法:

<template><div class="hello"><div class="opt-container"><div class="opt opt-increase" @click="increase">+</div><span class="opt">{{count}}</span><div class="opt opt-decrease" @click="decrease">-</div></div></div> </template><script>export default {name: 'HelloWorld',computed: {count() {return this.$store.state.count}},methods: {increase() {this.$store.dispatch('increase');},decrease() {this.$store.dispatch('decrease');}}} </script><!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped>.opt-container {font-size: 0px;}.opt {display: inline-block;text-align: center;height: 40px;width: 40px;border-radius: 20px;background-color: #efefef;line-height: 40px;user-select: none;font-size: 20px;margin: 0 10px;vertical-align: middle;} </style>

好啦!! 一個(gè)簡(jiǎn)單的vuexdemo就是是完成了,效果我就不演示了,跟我們一開始截屏是一樣的,所以現(xiàn)在不管是在項(xiàng)目哪個(gè)地方,我們只需要執(zhí)行

this.$store.dispatch('decrease'); this.$store.dispatch('increase');

都能改變demo頁(yè)面中的count值.

好啦~ 我們先看看我們的store文件:

Vue.use(Vuex); let state = {count: 0 }; const actions = {... }; const mutations = {... }; export default new Vuex.Store({state,actions,mutations });

可以看到我們?cè)诖a一開始執(zhí)行了:

Vue.use(Vuex);

官網(wǎng)也說了:

// 如果在模塊化構(gòu)建系統(tǒng)中,請(qǐng)確保在開頭調(diào)用了 Vue.use(Vuex)

我們都知道,當(dāng)執(zhí)行Vue.use(xx)方法后,Vue會(huì)執(zhí)行xx的install方法,并會(huì)傳遞當(dāng)前vue對(duì)象給第一個(gè)參數(shù),所以:
我們看看vuex源碼中干了什么,我們找到vuex源碼的install方法:

function install (_Vue) {if (Vue && _Vue === Vue) {{console.error('[vuex] already installed. Vue.use(Vuex) should be called only once.');}return}Vue = _Vue;applyMixin(Vue); }

繼續(xù)往下~

var applyMixin = function (Vue) {var version = Number(Vue.version.split('.')[0]);if (version >= 2) {Vue.mixin({ beforeCreate: vuexInit });} else {// override init and inject vuex init procedure// for 1.x backwards compatibility.var _init = Vue.prototype._init;Vue.prototype._init = function (options) {if ( options === void 0 ) options = {};options.init = options.init? [vuexInit].concat(options.init): vuexInit;_init.call(this, options);};}

我們用的vue版本是Vue.version = ‘2.5.16’;所以繼續(xù)往下

Vue.mixin({ beforeCreate: vuexInit });

所以當(dāng)用的了Vue.use(vuex),當(dāng)我們組件加載的時(shí)候,就會(huì)觸發(fā)組件的beforeCreate生命周期方法,然后就會(huì)走vuexInit方法:

function vuexInit () {//獲取當(dāng)前組件的vue對(duì)象var options = this.$options;// store injectionif (options.store) {//如果當(dāng)前vue對(duì)象是否包含store對(duì)象,則把當(dāng)前store對(duì)象賦給this.$store屬性this.$store = typeof options.store === 'function'? options.store(): options.store;} else if (options.parent && options.parent.$store) {//如果父組件包含了store對(duì)象,那么就把父控件的store對(duì)象給當(dāng)前vue組件this.$store = options.parent.$store;}}

看到了這是不是有點(diǎn)明白了,就是為了讓全局用一個(gè)store對(duì)象,然后通過組件的$store拿到當(dāng)前store對(duì)象,所以Vue.use(vuex)還是很重要的.

好啦~~ 看完了Vue.use(vuex)后,我們找到vuex的Store對(duì)象,首先找到Store的構(gòu)造方法:

var Store = function Store (options) {var this$1 = this;if ( options === void 0 ) options = {};// Auto install if it is not done yet and `window` has `Vue`.// To allow users to avoid auto-installation in some cases,// this code should be placed here. See #731if (!Vue && typeof window !== 'undefined' && window.Vue) {install(window.Vue);}{assert(Vue, "must call Vue.use(Vuex) before creating a store instance.");assert(typeof Promise !== 'undefined', "vuex requires a Promise polyfill in this browser.");assert(this instanceof Store, "Store must be called with the new operator.");}var plugins = options.plugins; if ( plugins === void 0 ) plugins = [];var strict = options.strict; if ( strict === void 0 ) strict = false;var state = options.state; if ( state === void 0 ) state = {};if (typeof state === 'function') {state = state() || {};}// store internal statethis._committing = false;this._actions = Object.create(null);this._actionSubscribers = [];this._mutations = Object.create(null);this._wrappedGetters = Object.create(null);this._modules = new ModuleCollection(options);this._modulesNamespaceMap = Object.create(null);this._subscribers = [];this._watcherVM = new Vue();// bind commit and dispatch to selfvar store = this;var ref = this;var dispatch = ref.dispatch;var commit = ref.commit;this.dispatch = function boundDispatch (type, payload) {return dispatch.call(store, type, payload)};this.commit = function boundCommit (type, payload, options) {return commit.call(store, type, payload, options)};// strict modethis.strict = strict;// init root module.// this also recursively registers all sub-modules// and collects all module getters inside this._wrappedGettersinstallModule(this, state, [], this._modules.root);// initialize the store vm, which is responsible for the reactivity// (also registers _wrappedGetters as computed properties)resetStoreVM(this, state);// apply pluginsplugins.forEach(function (plugin) { return plugin(this$1); });if (Vue.config.devtools) {devtoolPlugin(this);} };

代碼不是很多,我們首先看到:

if (!Vue && typeof window !== 'undefined' && window.Vue) {install(window.Vue);}

也就是當(dāng)我們沒有使用Vue.use的時(shí)候,如果window對(duì)象中有Vue對(duì)象,也會(huì)執(zhí)行跟Vue.use一樣的操作:

我們先簡(jiǎn)單的說一下vuex的原理哈,主要看構(gòu)造函數(shù)的這一行代碼:

// initialize the store vm, which is responsible for the reactivity// (also registers _wrappedGetters as computed properties)resetStoreVM(this, state);

字面上可以看出,就是注冊(cè)一個(gè)store的vm對(duì)象,那么vm對(duì)象到底是什么呢?我們繼續(xù)往下:

function resetStoreVM (store, state, hot) {var oldVm = store._vm;// bind store public gettersstore.getters = {};var wrappedGetters = store._wrappedGetters;var computed = {};forEachValue(wrappedGetters, function (fn, key) {// use computed to leverage its lazy-caching mechanismcomputed[key] = function () { return fn(store); };Object.defineProperty(store.getters, key, {get: function () { return store._vm[key]; },enumerable: true // for local getters});});// use a Vue instance to store the state tree// suppress warnings just in case the user has added// some funky global mixinsvar silent = Vue.config.silent;Vue.config.silent = true;store._vm = new Vue({data: {$$state: state},computed: computed});Vue.config.silent = silent;// enable strict mode for new vmif (store.strict) {enableStrictMode(store);}if (oldVm) {if (hot) {// dispatch changes in all subscribed watchers// to force getter re-evaluation for hot reloading.store._withCommit(function () {oldVm._data.$$state = null;});}Vue.nextTick(function () { return oldVm.$destroy(); });} }

先忽略其它代碼,我們看到這么一段:

store._vm = new Vue({data: {$$state: state},computed: computed});

好吧,小伙伴是不是明白了,其實(shí)就是創(chuàng)建了Vue對(duì)象,然后把我們創(chuàng)建在store的state對(duì)象給了data的$$state屬性,在vue中我們知道,data對(duì)象是響應(yīng)式的,所以當(dāng)我們發(fā)出一個(gè)action后,然后走到mutations,改變state的值,從而改變組件中綁定的值變換.

有點(diǎn)晚了,今天就先到這了,之后我會(huì)從vuex的dispatch—>mutations—>state的過程,帶著源碼一步一步走,最后再把a(bǔ)ctions的鉤子函數(shù)等等把vuex的源碼全部走一遍.

好啦~~ 大牛勿噴,下節(jié)見啦!!!!

總結(jié)

以上是生活随笔為你收集整理的前端入门之(vuex源码解析一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。