国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

一篇文章讓你徹底了解vuex的使用及原理(上)

這篇具有很好參考價(jià)值的文章主要介紹了一篇文章讓你徹底了解vuex的使用及原理(上)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

vuex詳解

文章講解的Vuex的版本為4.1.0,會(huì)根據(jù)一些api來(lái)深入源碼講解,幫助大家更快掌握vuex的使用。

vuex的使用

使用Vue實(shí)例的use方法把Vuex實(shí)例注入到Vue實(shí)例中。

const store = createStore({...})
createApp(App).use(store)

use方法執(zhí)行的是插件的中的install方法

src/store.js

export class Store {
  // ...
  // app 是vue實(shí)例
  install(app, injectKey) {
    app.provide(injectKey || storeKey, this)
    app.config.globalProperties.$store = this
    ...
  }
}

從上面可以看到Vue實(shí)例通過(guò) provide方法把 store 實(shí)例 provide 到了根實(shí)例中。同時(shí)添加了一個(gè)全局變量$store,在每個(gè)組件中都可以通過(guò)this.$store來(lái)訪問(wèn)store實(shí)例。

app.provide 是給 Composition API 方式編寫(xiě)的組件用的,因?yàn)橐坏┦褂昧?Composition API ,我們?cè)诮M件中想訪問(wèn) store 的話會(huì)在 setup 函數(shù)中通過(guò) useStore API 拿到.

import { useStore } from 'vuex'
export default {
  setup() {
    const store = useStore()
  }
}

useStore的實(shí)現(xiàn)也在src/injectKey.js文件中:

import { inject } from 'vue'
export const storeKey = 'store'
export function useStore (key = null) {
  return inject(key !== null ? key : storeKey)
}

Vuex 就是利用了 provide/inject 依賴注入的 API 實(shí)現(xiàn)了在組件中訪問(wèn)到 store,由于是通過(guò) app.provide 方法把 store 實(shí)例 provide 到根實(shí)例中,所以在 app 內(nèi)部的任意組件中都可以 inject store 實(shí)例并訪問(wèn)了。

除了 Composition API,Vue3.x 依然支持 Options API 的方式去編寫(xiě)組件,在 Options API 組件中我們就可以通過(guò) this.$store 訪問(wèn)到 store 實(shí)例,因?yàn)閷?shí)例的查找最終會(huì)找到全局 globalProperties 中的屬性(globalProperties添加一個(gè)可以在應(yīng)用的任何組件實(shí)例中訪問(wèn)的全局 property。組件的 property 在命名沖突具有優(yōu)先權(quán))。

provide/injectVuex 中的作用就是讓組件可以訪問(wèn)到 store 實(shí)例。

響應(yīng)式狀態(tài)

state

state中設(shè)置的屬性是響應(yīng)式的

使用:

// 設(shè)置state
const state = createStore({
  state: {
    value: 1
  }
})

// 在組件上使用
const Com = {
  template: `<div>{{ $store.state.value }}</div>`,
}

之后會(huì)在Store類(lèi)中調(diào)用一個(gè)resetStoreState方法,將傳入的state通過(guò)reactive方法設(shè)置成響應(yīng)式。

export function resetStoreState (store, state, hot) {
  ...
  store._state = reactive({
    data: state
  })
  ...
}

getters

可以從 store 中的 state 中派生出一些狀態(tài)。

// 設(shè)置state和getters
const store = new Vuex.Store({
  state: {
    value: 1,
  },
  getters: {
    getterVal(state, getters) {
      return state.value + 1;
    }
  }
})

// 在組件上使用
const Com = {
  template: `<div>{{$store.getters.getterVal}}</div>`
}

也可以通過(guò)讓getter返回一個(gè)函數(shù)來(lái)實(shí)現(xiàn)給getter傳遞參數(shù)。

// 設(shè)置state和getters
const store = new Vuex.Store({
  state: {
    value: 1,
  },
  getters: {
    getterVal(state, getters) {
      return function(num) {
        return state.val + num;
      };
    }
  }
})

// 在組件上使用
const Com = {
  template: `<div>{{$store.getters.getterVal(3)}}</div>`
}

同時(shí)vuex內(nèi)部對(duì)getter有進(jìn)行緩存處理,只有當(dāng)依賴的state發(fā)生改變后才會(huì)重新收集。

來(lái)看看vuex內(nèi)部是如何實(shí)現(xiàn)getter的:

  1. 類(lèi)Store中會(huì)調(diào)用installModule會(huì)對(duì)傳入的模塊進(jìn)行處理(詳情請(qǐng)看下面的模塊化部分,里邊會(huì)對(duì)模塊里的getters處理)
// src/store-util.js
// 對(duì)所有模塊中的getters進(jìn)行處理
module.forEachGetter((getter, key) => {
  const namespacedType = namespace + key
  registerGetter(store, namespacedType, getter, local)
})

function registerGetter (store, type, rawGetter, local) {
  // 去重處理
  if (store._wrappedGetters[type]) {
    if (__DEV__) {
      console.error(`[vuex] duplicate getter key: ${type}`)
    }
    return
  }
  // 往store實(shí)例的_wrappedGetters存儲(chǔ)getters,這樣就可以通過(guò)store.getters['xx/xxx']來(lái)訪問(wèn)
  store._wrappedGetters[type] = function wrappedGetter (store) {
    // 調(diào)用模塊中設(shè)置的getter方法,可以看到這里是傳入了4個(gè)參數(shù)
    return rawGetter(
      local.state, // local state
      local.getters, // local getters
      store.state, // root state
      store.getters // root getters
    )
  }
}
  1. 在類(lèi)Store中調(diào)用resetStoreState方法中對(duì)使用computed方法對(duì)getter進(jìn)行計(jì)算后緩存。
export function resetStoreState (store, state, hot) {
  ...
  const wrappedGetters = store._wrappedGetters
  const scope = effectScope(true)
  scope.run(() => {
    forEachValue(wrappedGetters, (fn, key) => {
      computedObj[key] = partial(fn, store)
      computedCache[key] = computed(() => computedObj[key]())
      Object.defineProperty(store.getters, key, {
        get: () => computedCache[key].value,
        enumerable: true
      })
    })
  })
  ...
}

Mutations

更改 Vuexstore 中的狀態(tài)的唯一方法是提交 mutation。Vuex 中的 mutation 非常類(lèi)似于事件:每個(gè) mutation 都有一個(gè)事件類(lèi)型 (type)和一個(gè)回調(diào)函數(shù) (handler)。這個(gè)回調(diào)函數(shù)就是實(shí)際進(jìn)行狀態(tài)更改的地方。

const store = createStore({
  state: {
    value: 1
  },
  mutations: {
    increment (state, payload) {
      state.value++
    }
  }
})

installModule方法中,對(duì)模塊中的mutations進(jìn)行注冊(cè),

// src/store-util.js
function registerMutation (store, type, handler, local) {
  const entry = store._mutations[type] || (store._mutations[type] = [])
  entry.push(function wrappedMutationHandler (payload) {
    handler.call(store, local.state, payload)
  })
}

把模塊中的mutations全部添加到Store實(shí)例中的_mutations對(duì)象中,將mutations中的this指向Store實(shí)例,并傳入兩個(gè)參數(shù):

  • state: 當(dāng)前模塊的state(具體詳解請(qǐng)看模塊化部分)
  • payload: 通過(guò)commit中傳入的參數(shù)。

像上面的demo_mutations值為{increment: [fn]}

commit觸發(fā)mutation

語(yǔ)法:
commit(type: string, payload?: any, options?: Object)
commit(mutation: Object, options?: Object)

通過(guò)使用commit方法來(lái)觸發(fā)對(duì)應(yīng)的mutation

store.commit('increment');

commit可以接受額外的參數(shù)(payload)來(lái)為mutation傳入?yún)?shù)。

const store = createStore({
  state: {
    value: 1
  },
  mutations: {
    increment (state, num) {
      state.value += num;
    }
  }
})

store.commit('increment', 2);

在大多數(shù)情況下,載荷應(yīng)該是一個(gè)對(duì)象,這樣可以包含多個(gè)字段并且記錄的 mutation 會(huì)更易讀

在類(lèi)Store中定義了commit方法,因?yàn)?code>commit方法內(nèi)部需要使用到Store實(shí)例中的方法,因此需要使用call方法把this指向Store實(shí)例。

// src/store.js
export class Store {
  constructor (options = {}) {
    this._mutations = Object.create(null)
    // 改變this
    this.commit = function boundCommit (type, payload, options) {
      return commit.call(store, type, payload, options)
  }
  ...
  commit (_type, _payload, _options) {
    const {
      type,
      payload,
      options
    } = unifyObjectStyle(_type, _payload, _options)

    const mutation = { type, payload }
    const entry = this._mutations[type]
    ...

    this._withCommit(() => {
      entry.forEach(function commitIterator (handler) {
        handler(payload)
      })
    })
    ...
  }
}

// src/store-util.js
export function unifyObjectStyle (type, payload, options) {
  if (isObject(type) && type.type) {
    options = payload
    payload = type
    type = type.type
  }
  return { type, payload, options }
}

可以看到在處理傳入commit的參數(shù)時(shí)Vuex進(jìn)行了處理??梢酝?code>commit傳入對(duì)象形式的配置。

const store = createStore({
  state: {
    value: 1
  },
  mutations: {
    increment (state, payload) {
      state.value += payload.value;
    }
  }
})
store.commit({
  type: 'increment',
  value: 1
})

mutation中必須是同步函數(shù),如果mutation是一個(gè)異步函數(shù),異步修改狀態(tài),雖然也會(huì)使?fàn)顟B(tài)正常更新,但是會(huì)導(dǎo)致開(kāi)發(fā)者工具有時(shí)無(wú)法追蹤到狀態(tài)的變化,調(diào)試起來(lái)就會(huì)很困難。

訂閱mutations

Vuex提供了subscribe方法用來(lái)訂閱 storemutation,當(dāng)mutations執(zhí)行完后就會(huì)觸發(fā)訂閱回調(diào)。

語(yǔ)法:subscribe(handler, options)

  • handler: 處理函數(shù)
  • options: 配置
    • prepend: Boolean值,把處理函數(shù)添加到訂閱函數(shù)鏈的最開(kāi)始。
const store = createStore(...)

// subscribe方法的返回值是一個(gè)取消訂閱的函數(shù)
const unsubscribe = store.subscribe((mutation, state) => {
  console.log(mutation)
})
// 你可以調(diào)用 unsubscribe 來(lái)停止訂閱。
// unsubscribe()

const unsubscribe2 = store.subscribe((mutation, state) => {
  console.log('在訂閱函數(shù)鏈頭部,最先執(zhí)行')
}, {prepend: true})

訂閱的源碼實(shí)現(xiàn)非常簡(jiǎn)單,使用一個(gè)數(shù)組來(lái)維護(hù)訂閱函數(shù)。在觸發(fā)commit方法內(nèi)部添加執(zhí)行訂閱方法即可。

// src/store.js
export class Store {
  constructor (options = {}) {
    this._subscribers = [];
    ...
  }
  commit() {
    ...
    const mutation = { type, payload }
    // 執(zhí)行mutation
    this._withCommit(() => {
      entry.forEach(function commitIterator (handler) {
        handler(payload)
      })
    })
    // 在mutation執(zhí)行完后執(zhí)行訂閱
    this._subscribers
      .slice()
      .forEach(sub => sub(mutation, this.state))
  }
  subscribe (fn, options) {
    return genericSubscribe(fn, this._subscribers, options)
  }
  ...
}

// src/store-util.js
export function genericSubscribe (fn, subs, options) {
  if (subs.indexOf(fn) < 0) {
    // 如果傳入了prepend: true 把處理函數(shù)添加到訂閱函數(shù)鏈的最開(kāi)始
    options && options.prepend
      ? subs.unshift(fn)
      : subs.push(fn)
  }
  // 返回一個(gè)取消訂閱的方法
  return () => {
    const i = subs.indexOf(fn)
    if (i > -1) {
      subs.splice(i, 1)
    }
  }
}

Actions

Action 類(lèi)似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接變更狀態(tài)。
  • Action 可以包含任意異步操作。
const store = createStore({
  state: {
    value: 1
  },
  mutations: {
    increment (state, payload) {
      state.value += payload.value
    }
  },
  actions: {
    emitIncrement(context, payload) {
      context.commit('increment', payload);
      // action同樣可以改變state中的數(shù)據(jù),但是最好不要這樣使用,在嚴(yán)格模式下控制臺(tái)會(huì)拋異常且action是異步的,不方便DevTool 調(diào)試
      // context.state.value++;
    }
  },
})

installModule方法中,對(duì)模塊中的actions進(jìn)行注冊(cè)。跟mutations一樣的是也是也把所有的action方法放在一個(gè)變量_actions下,同時(shí)this也指向Store實(shí)例,并傳入兩個(gè)參數(shù):

  • context: 當(dāng)前模塊的上下文(具體詳解請(qǐng)看模塊化部分)
  • payload: 通過(guò)dispatch中傳入的參數(shù)。
module.forEachAction((action, key) => {
  const type = action.root ? key : namespace + key
  const handler = action.handler || action
  registerAction(store, type, handler, local)
})

function registerAction (store, type, handler, local) {
  const entry = store._actions[type] || (store._actions[type] = [])
  entry.push(function wrappedActionHandler (payload) {
    let res = handler.call(store, {
      dispatch: local.dispatch,
      commit: local.commit,
      getters: local.getters,
      state: local.state,
      rootGetters: store.getters,
      rootState: store.state
    }, payload)
    // 強(qiáng)行轉(zhuǎn)化為promise,在dispatch就可以統(tǒng)一處理
    if (!isPromise(res)) {
      res = Promise.resolve(res)
    }
    ...
    return res
  })
}

值得注意的是在action執(zhí)行完后是返回一個(gè)Promise格式的值。詳細(xì)看下面的dispatch部分。

dipatch分發(fā)actions

語(yǔ)法:
dispatch(type: string, payload?: any, options?: Object): Promise<any>
dispatch(action: Object, options?: Object): Promise<any>

store.dispatch('emitIncrement', {value: 1})
// 對(duì)象形式
store.dispatch({
  type: 'emitIncrement',
  value: 1
})

通過(guò)使用dispatch方法來(lái)觸發(fā)對(duì)應(yīng)的action

// src/store.js
export class Store {
  dispatch (_type, _payload) {
    // 跟mutations一樣處理傳入對(duì)象的形式
    const {
      type,
      payload
    } = unifyObjectStyle(_type, _payload)

    const action = { type, payload }
    const entry = this._actions[type]
    ...

    const result = entry.length > 1
      ? Promise.all(entry.map(handler => handler(payload)))
      : entry[0](payload)
    ...
  }
}

可以看到在執(zhí)行action時(shí)如果對(duì)應(yīng)的action數(shù)組中存在多個(gè),用了Promise.all來(lái)處理,這是為了當(dāng)type對(duì)應(yīng)的所有的action都執(zhí)行完后才繼續(xù)執(zhí)行這樣才能保證訂閱是在action執(zhí)行之后觸發(fā)。

訂閱actions

mutation一樣,action也可以添加訂閱

語(yǔ)法:subscribeAction(handler: Function, options?: Object): Function

返回值也是一個(gè)取消訂閱方法。

  • handler: 處理函數(shù)
  • options: 配置
    • before: 在action執(zhí)行前觸發(fā)(默認(rèn))
    • after: 在action執(zhí)行后觸發(fā)
    • error: 捕獲分發(fā) action 的時(shí)候被拋出的錯(cuò)誤
    • prepend: Boolean值,把處理函數(shù)添加到訂閱函數(shù)鏈的最開(kāi)始。

相比起mutation的訂閱,action的訂閱較為復(fù)雜一點(diǎn)。

store.subscribeAction((action, state) => {
  console.log(action)
})

store.subscribeAction((action, state) => {
  console.log('在訂閱函數(shù)鏈頭部,最先執(zhí)行')
}, {prepend: true})

store.subscribeAction({
  before: (action, state) => {
    console.log(`before action`)
  },
  after: (action, state) => {
    console.log(`after action`)
  },
  error: (action, state, error) => {
    console.log(`error action`)
    console.error(error)
  }
})

來(lái)看看訂閱action的添加和觸發(fā)相關(guān)的實(shí)現(xiàn)原理:

export class Store {
  subscribeAction (fn, options) {
    // 當(dāng)傳入的第一個(gè)參數(shù)為函數(shù)時(shí),封裝成{before:fn}的形式
    const subs = typeof fn === 'function' ? { before: fn } : fn
    // 把訂閱方法放入_actionSubscribers數(shù)組中
    return genericSubscribe(subs, this._actionSubscribers, options)
  }
  dispatch (_type, _payload) {
    const action = { type, payload }
    const entry = this._actions[type]
    ...

    // 執(zhí)行before相關(guān)訂閱
    try {
      this._actionSubscribers
        .slice()
        .filter(sub => sub.before)
        .forEach(sub => sub.before(action, this.state))
    }
    ...

    const result = entry.length > 1
      ? Promise.all(entry.map(handler => handler(payload)))
      : entry[0](payload)

    // 返回一個(gè)promise
    return new Promise((resolve, reject) => {
      // 對(duì)于同步函數(shù)而已,因此在注冊(cè)階段就直接使用Promise.resolve處理能異步函數(shù)了,所以統(tǒng)一使用then獲取執(zhí)行結(jié)果
      result.then(res => {
        try {
          // 執(zhí)行after訂閱者
          this._actionSubscribers
            .filter(sub => sub.after)
            .forEach(sub => sub.after(action, this.state))
        }
        ...
        resolve(res)
      }, error => {
        try {
          // 執(zhí)行error訂閱者
          this._actionSubscribers
            .filter(sub => sub.error)
            .forEach(sub => sub.error(action, this.state, error))
        }
        ...
        reject(error)
      })
    })
  }
}

模塊化

如果只使用單一狀態(tài)樹(shù),應(yīng)用的所有狀態(tài)就會(huì)集中到一個(gè)比較大的對(duì)象,store 對(duì)象就有可能變得相當(dāng)臃腫。Vuex 可以允許將 store 分割成模塊(module)。每個(gè)模塊甚至是嵌套子模塊擁有 state、getters等。

例如

const nestedModule = {
  namespaced: true,
  state: {
    a: 1
  },
  getters: {},
  mutations: {},
  actions: {},
}
const module = {
  state: {},
  getters: {},
  mutations: {},
  actions: {},
  modules: {
    nested: nestedModule
  }
}
const store = createStore(module);
store.state.nested  // {a: 1} 獲取嵌套module的狀態(tài)

模塊解析

Vuex實(shí)例創(chuàng)建時(shí),會(huì)對(duì)傳入的模塊進(jìn)行解析

export class Store {
  constructor(options) {
    this._modules = new ModuleCollection(options)
    installModule(this, state, [], this._modules.root)
  }
}

初始化ModuleCollection時(shí)會(huì)對(duì)模塊進(jìn)行注冊(cè):

// src/module/module-collection.js
export default class ModuleCollection {
  constructor (rawRootModule) {
    this.register([], rawRootModule, false)
  }
  register (path, rawModule, runtime = true) {
    // 將每個(gè)模塊使用一個(gè)module對(duì)象來(lái)展示
    const newModule = new Module(rawModule, runtime)
    if (path.length === 0) {
      this.root = newModule
    } else {
      // 將嵌套模塊添加到父模塊的_children屬性中
      const parent = this.get(path.slice(0, -1))
      parent.addChild(path[path.length - 1], newModule)
    }

    // 注冊(cè)嵌套模塊
    if (rawModule.modules) {
      forEachValue(rawModule.modules, (rawChildModule, key) => {
        this.register(path.concat(key), rawChildModule, runtime)
      })
    }
  }
}

最后形成一個(gè)便于Vuex處理的對(duì)象:

this._modules = {
  root: {
    runtime: Boolean,
    state: {},
    _children: [],
    _rawModule: {},
    namespaced: Boolean
  }
}

installModule方法非常重要,里邊會(huì)對(duì)嵌套module進(jìn)行解析,使得嵌套內(nèi)部可以在調(diào)用dispatch、commit的時(shí)候能找到對(duì)應(yīng)的actionmutation。

// src/store-utils.js installModule
const isRoot = !path.length
const namespace = store._modules.getNamespace(path)

if (!isRoot && !hot) {
  const parentState = getNestedState(rootState, path.slice(0, -1))
  const moduleName = path[path.length - 1]
  store._withCommit(() => {
    ...
    // 將子模塊的state添加到父模塊的state中
    parentState[moduleName] = module.state
  })
}

namespaced的作用:
在子模塊中添加namespaced: true,根模塊的會(huì)根據(jù)模塊的modules字段中的key作為索引將子模塊中mutations、actions、getters存儲(chǔ)在根模塊中。例如:

mutations: {'childModule/module1', [fn]}

在調(diào)用commit或者dispatch方法的時(shí)候就可以根據(jù)這個(gè)key找到對(duì)應(yīng)子模塊中的mutationaction
如果子模塊中沒(méi)有設(shè)置namespaced: true,那么在根模塊中的_actions等字段的key就為對(duì)應(yīng)的子模塊中的actions里定義的key,如果模塊非常多的時(shí)候,容易造成命名沖突。而vuex也考慮到這種情況,因此key對(duì)應(yīng)的值的類(lèi)型為數(shù)組,這樣即使沖突了,也會(huì)執(zhí)行數(shù)組中所有的方法,不過(guò)這樣就會(huì)導(dǎo)致觸發(fā)其他模塊中非必要的action、mutation等。

// 如兩個(gè)子模塊都存在一個(gè)increment的mutation,同時(shí)都沒(méi)有設(shè)置 namespaced: true,那么在根模塊的_mutations就為
_mutations: { 'increment', [fn1, fn2] }
// 調(diào)用 store.commit('increment'),fn1, fn2都會(huì)執(zhí)行

將子模塊的state添加到父模塊的state中,這樣就可以通過(guò)store.state.childModule.state.xxx進(jìn)行訪問(wèn)。

為模塊創(chuàng)建了一個(gè)執(zhí)行上下文,當(dāng)觸發(fā)commit或者dispatch時(shí)就會(huì)根據(jù)namespaced找到對(duì)應(yīng)的模塊中的mutations或者actions中的方法。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-422278.html

// src/store-utils.js installModule
// 為當(dāng)前模塊添加一個(gè)上下文
const local = module.context = makeLocalContext(store, namespace, path)

module.forEachMutation((mutation, key) => {
  const namespacedType = namespace + key
  registerMutation(store, namespacedType, mutation, local)
})

// src/store-utils.js
function makeLocalContext (store, namespace, path) {
  const noNamespace = namespace === ''
  const local = {
    dispatch: noNamespace ? store.dispatch : (_type, _payload, _options) => {
      ...

      if (!options || !options.root) {
        type = namespace + type
        ...
      }
      return store.dispatch(type, payload)
    },
    // commit 類(lèi)似
  }
  ...

  return local
}

到了這里,關(guān)于一篇文章讓你徹底了解vuex的使用及原理(上)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 這篇文章,讓你了解ERC-1155 多代幣標(biāo)準(zhǔn)協(xié)議

    用于多種代幣管理的合約標(biāo)準(zhǔn)接口。 單個(gè)部署的合約可以包括同質(zhì)化代幣、非同質(zhì)化代幣或其他配置(如半同質(zhì)化代幣)的任何組合。 ERC1155 的顯著特點(diǎn)是它使用單個(gè)智能合約一次代表多個(gè)代幣。這就是為什么它的balanceOf功能不同于 ERC20 和 ERC777 的原因:它有一個(gè)額外的id參

    2024年02月01日
    瀏覽(18)
  • 通過(guò)一篇文章讓你了解Linux的重要性

    通過(guò)一篇文章讓你了解Linux的重要性

    Linux是一種自由和開(kāi)放源代碼的操作系統(tǒng),由林納斯·托瓦茲于1991年首次發(fā)布。它基于Unix,具有模塊化設(shè)計(jì),支持多任務(wù)和多用戶,能在多種硬件平臺(tái)上運(yùn)行。Linux系統(tǒng)在全球范圍內(nèi)得到廣泛應(yīng)用,包括服務(wù)器、移動(dòng)設(shè)備、嵌入式系統(tǒng)等領(lǐng)域。其強(qiáng)大的功能、穩(wěn)定性和安全性

    2024年04月15日
    瀏覽(25)
  • 一篇文章讓你了解ADAS-HIL測(cè)試方案

    一篇文章讓你了解ADAS-HIL測(cè)試方案

    ADA S (Advanced Driber Assistant System),高級(jí)駕駛輔助系統(tǒng), 先進(jìn)駕駛輔 助系統(tǒng),作用于輔助汽車(chē)駕駛,通過(guò)感知、決策和執(zhí)行,幫助駕駛員察覺(jué)可能發(fā)生的危險(xiǎn),是提高安全性的主動(dòng)安全技術(shù),保障行駛安全,已成當(dāng)前汽車(chē)裝載必備系統(tǒng);并普遍認(rèn)為是實(shí)現(xiàn)自動(dòng)駕駛AD的過(guò)程性

    2023年04月08日
    瀏覽(19)
  • 一篇文章讓你了解nginx和lua腳本(Nginx詳解)

    一篇文章讓你了解nginx和lua腳本(Nginx詳解)

    靜態(tài)資源部署 Rewrite地址重寫(xiě) 正則表達(dá)式 反向代理 負(fù)載均衡 輪詢、加權(quán)輪詢、ip_hash、url_hash、fair Web緩存 環(huán)境部署 高可用的環(huán)境 用戶認(rèn)證模塊… nginx二進(jìn)制可執(zhí)行文件 nginx.conf配置文件 error.log錯(cuò)誤的日志記錄 access.log訪問(wèn)日志記錄 首先我們來(lái)學(xué)習(xí)下,我們的配置文件,n

    2024年02月10日
    瀏覽(32)
  • 一篇文章徹底了解網(wǎng)絡(luò)字節(jié)序和主機(jī)字節(jié)序,初學(xué)者進(jìn)來(lái),不走彎路

    一篇文章徹底了解網(wǎng)絡(luò)字節(jié)序和主機(jī)字節(jié)序,初學(xué)者進(jìn)來(lái),不走彎路

    目錄 1.什么是字節(jié)序? 2.大端字節(jié)序和小端字節(jié)序 3.主機(jī)字節(jié)序和網(wǎng)絡(luò)字節(jié)序 4.不同類(lèi)型數(shù)據(jù)傳輸處理流程對(duì)比 5.設(shè)計(jì)一個(gè)小程序來(lái)判斷當(dāng)前機(jī)器的字節(jié)序? 6.大小端轉(zhuǎn)換方法? 字節(jié)序,字節(jié)在內(nèi)存中排列順序 計(jì)算機(jī)存儲(chǔ)數(shù)據(jù)方式是從內(nèi)存增長(zhǎng)方向存儲(chǔ) 圖 1 計(jì)算機(jī)存儲(chǔ)方式 網(wǎng)

    2024年02月03日
    瀏覽(19)
  • 你真的學(xué)懂if語(yǔ)句了嘛,看完這篇文章你一定會(huì)讓你有所收獲,徹底玩轉(zhuǎn)if語(yǔ)句!

    你真的學(xué)懂if語(yǔ)句了嘛,看完這篇文章你一定會(huì)讓你有所收獲,徹底玩轉(zhuǎn)if語(yǔ)句!

    ?? 鴿芷咕 :個(gè)人主頁(yè) ??? 個(gè)人專(zhuān)欄 :《C語(yǔ)言初階篇》 《C語(yǔ)言進(jìn)階篇》 ??生活的理想,就是為了理想的生活! ?? ?? hello! 各位寶子們大家好啊,相信大家都多多少少了解過(guò)if語(yǔ)句吧,但是你真的有了解過(guò),所有if語(yǔ)句的細(xì)節(jié)嗎?學(xué)完這篇文章你將知道if語(yǔ)句的所有知識(shí)

    2024年02月11日
    瀏覽(42)
  • 【Spring框架】一篇文章帶你徹底搞懂Spring解決循環(huán)依賴的底層原理

    【Spring框架】一篇文章帶你徹底搞懂Spring解決循環(huán)依賴的底層原理

    目錄 一、前言 二、什么是循環(huán)依賴 三、Spring Bean 的循環(huán)依賴問(wèn)題 3.1 Bean 的創(chuàng)建步驟 3.2 為什么 Spring Bean 會(huì)產(chǎn)生循環(huán)依賴問(wèn)題? 3.3 什么情況下循環(huán)依賴可以被處理? 四、Spring 如何解決循環(huán)依賴問(wèn)題? 4.0 什么是三級(jí)緩存 4.1 簡(jiǎn)單的循環(huán)依賴(沒(méi)有AOP) 4.1.0 創(chuàng)建Bean的前期流

    2024年04月17日
    瀏覽(32)
  • 一篇文章帶你了解-selenium工作原理詳解

    一篇文章帶你了解-selenium工作原理詳解

    前言 Selenium是一個(gè)用于Web應(yīng)用程序自動(dòng)化測(cè)試工具。Selenium測(cè)試直接運(yùn)行在瀏覽器中,就像真正的用戶在操作一樣。支持的瀏覽器包括IE(7, 8, 9, 10, 11),Mozilla Firefox,Safari,Google Chrome,Opera等。 主要功能包括:測(cè)試與瀏覽器的兼容性——測(cè)試你的應(yīng)用程序看是否能夠很好得

    2024年02月10日
    瀏覽(26)
  • C++初階之一篇文章讓你掌握vector(理解和使用)

    C++初階之一篇文章讓你掌握vector(理解和使用)

    在C++中,std::vector是標(biāo)準(zhǔn)模板庫(kù)(STL)中的一種動(dòng)態(tài)數(shù)組容器,它可以存儲(chǔ)任意類(lèi)型的元素,并且能夠自動(dòng)調(diào)整大小。std::vector提供了許多方便的成員函數(shù),使得對(duì)數(shù)組的操作更加簡(jiǎn)單和高效。 vector聲明 : template class T, class Alloc = allocatorT ; 這是 std::vector 的一般模板定義。它

    2024年02月14日
    瀏覽(29)
  • 一篇文章讓你完全掌握使用Git推送代碼到新版GitCode

    一篇文章讓你完全掌握使用Git推送代碼到新版GitCode

    GitCode是一款基于Git的在線代碼托管和協(xié)作工具,提供代碼版本控制、代碼托管、代碼評(píng)審、項(xiàng)目管理等功能。它支持多種編程語(yǔ)言,包括 Java 、 Python 、 C++ 等,可幫助開(kāi)發(fā)者高效協(xié)作,提高代碼質(zhì)量和開(kāi)發(fā)效率。GitCode還提供豐富的 API 接口,支持與其他系統(tǒng)集成,方便開(kāi)發(fā)

    2024年03月25日
    瀏覽(24)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包