当前位置: 首页 > news >正文

门户网站是什么中国轻工建设协会网站

门户网站是什么,中国轻工建设协会网站,有什么网站可以免费建站免费建网站,网站海外推广外包前言#xff1a;最近接触到一种新的#xff08;对我个人而言#xff09;状态管理方式#xff0c;它没有采用现有的开源库#xff0c;如redux、mobx等#xff0c;也没有使用传统的useContext#xff0c;而是用useState useEffect写了一个发布订阅者模式进行状态管理最近接触到一种新的对我个人而言状态管理方式它没有采用现有的开源库如redux、mobx等也没有使用传统的useContext而是用useState useEffect写了一个发布订阅者模式进行状态管理这一点对我来说感觉比较新奇以前从没接触过这种写法于是决定研究一下目前比较常用的状态管理方式。 ps这里谈到的状态管理是指全局状态管理局部的使用useState即可 ​ 状态管理方式 目前比较常用的状态管理方式有hooks、redux、mobx三种下面我将详细介绍一下这三类的使用方法以及分析各自的优缺点以供各位进行参考。 Hooks状态管理 用hooks进行状态管理主要有两种方式 useContextuseReduceruseStateuseEffect useContextuseReducer 使用方法 1.创建store和reducer以及全局context src/store/reducer.ts import React from react; // 初始状态 export const state {count: 0,name: ry, };// reducer 用于修改状态 export const reducer (state, action) {const { type, payload } action;switch (type) {case ModifyCount:return {...state,count: payload,};case ModifyName:return {...state,name: payload,};default: {return state;}} };export const GlobalContext React.createContext(null);2.根组件通过 Provider 注入 context src/App.tsx import React, { useReducer } from react; import ./index.less import { state as initState, reducer, GlobalContext} from ./store/reducer import Count from ./components/Count import Name from ./components/Nameexport default function () {const [state, dispatch] useReducer(reducer, initState);return (divGlobalContext.Provider value{{state, dispatch}}Count /Name //GlobalContext.Provider/div) }3.在组件中使用 src/components/Count/index.tsx import { GlobalContext } from /store/reducer; import React, { FC, useContext } from react;const Count: FC () {const ctx useContext(GlobalContext)return (divpcount:{ctx.state.count}/pbutton onClick{() ctx.dispatch({ type: ModifyCount, payload: ctx.state.count1 })}1/button/div); };export default Count;参考 前端进阶面试题详细解答 src/components/Name/index.tsx import { GlobalContext } from /store/reducer; import React, { FC, useContext } from react;const Name: FC () {const ctx useContext(GlobalContext)console.log(NameRerendered)return (divpname:{ctx.state.name}/p/div); };export default Name;useStateuseEffect 使用方法 1.创建state和reducer src/global-states.ts // 初始state let globalState: GlobalStates {count: 0,name: ry }// reducer export const modifyGlobalStates (operation: GlobalStatesModificationType, payload: any ) {switch (operation) {case GlobalStatesModificationType.MODIFY_COUNT:globalState Object.assign({}, globalState, { count: payload })breakcase GlobalStatesModificationType.MODIFY_NAME:globalState Object.assign({}, globalState, { name: payload })break}broadcast() }src/global-states.type.ts export interface GlobalStates {count: number;name: string; }export enum GlobalStatesModificationType {MODIFY_COUNT,MODIFY_NAME }2.写一个发布订阅模式让组件订阅globalState src/global-states.ts import { useState, useEffect } from react import {GlobalStates,GlobalStatesModificationType } from ./global-states.typelet listeners []let globalState: GlobalStates {count: 0,name: ry } // 发布所有订阅者收到消息执行setState重新渲染 const broadcast () {listeners.forEach((listener) {listener(globalState)}) }export const modifyGlobalStates (operation: GlobalStatesModificationType, payload: any ) {switch (operation) {case GlobalStatesModificationType.MODIFY_COUNT:globalState Object.assign({}, globalState, { count: payload })breakcase GlobalStatesModificationType.MODIFY_NAME:globalState Object.assign({}, globalState, { name: payload })break}// 状态改变即发布broadcast() }// useEffect useState实现发布订阅 export const useGlobalStates () {const [value, newListener] useState(globalState)useEffect(() {// newListener是新的订阅者listeners.push(newListener)// 组件卸载取消订阅return () {listeners listeners.filter((listener) listener ! newListener)}})return value }3.组件中使用 src/App.tsx import React from react import ./index.less import Count from ./components/Count import Name from ./components/Nameexport default function () {return (divCount /Name //div) }src/components/Count/index.tsx import React, { FC } from react import { useGlobalStates, modifyGlobalStates } from /store/global-states import { GlobalStatesModificationType } from /store/global-states.typeconst Count: FC () {// 调用useGlobalStates()即订阅globalStates()const { count } useGlobalStates()return (divpcount:{count}/pbuttononClick{() modifyGlobalStates( GlobalStatesModificationType.MODIFY_COUNT, count 1 ) } 1 /button/div) }export default Countsrc/components/Name/index.tsx import React, { FC } from react import { useGlobalStates } from /store/global-statesconst Count: FC () {const { name } useGlobalStates()console.log(NameRerendered)return (divpname:{name}/p/div) }export default Count优缺点分析 由于以上两种都是采用hooks进行状态管理这里统一进行分析 优点 代码比较简洁如果你的项目比较简单只有少部分状态需要提升到全局大部分组件依旧通过本地状态来进行管理。这时使用 hookst进行状态管理就挺不错的。杀鸡焉用牛刀。 缺点 两种hooks管理方式都有一个很明显的缺点会产生大量的无效rerender如上例中的Count和Name组件当state.count改变后Name组件也会rerender尽管他没有使用到state.count。这在大型项目中无疑是效率比较低的。 Redux状态管理 使用方法 1.引入redux yarn add redux react-redux types/react-redux redux-thunk2.新建reducer 在src/store/reducers文件夹下新建addReducer.ts可建立多个reducer import * as types from ../action.types import { AnyAction } from redux// 定义参数接口 export interface AddState {count: numbername: string }// 初始化state let initialState: AddState {count: 0,name: ry }// 返回一个reducer export default (state: AddState initialState, action: AnyAction): AddState {switch (action.type) {case types.ADD:return { ...state, count: state.count action.payload }default:return state} }在src/stores文件夹下新建action.types.ts 主要用于声明action类型 export const ADD ADD export const DELETE DELETE3.合并reducer 在src/store/reducers文件夹下新建index.ts import { combineReducers, ReducersMapObject, AnyAction, Reducer } from redux import addReducer, { AddState } from ./addReducer// 如有多个reducer则合并reducers模块化 export interface CombinedState {addReducer: AddState } const reducers: ReducersMapObjectCombinedState, AnyAction {addReducer } const reducer: ReducerCombinedState, AnyAction combineReducers(reducers)export default reducer3.创建store 在src/stores文件夹下新建index.ts import {createStore,applyMiddleware,StoreEnhancer,StoreEnhancerStoreCreator,Store } from redux import thunk from redux-thunk import reducer from ./reducers// 生成store增强器 const storeEnhancer: StoreEnhancer applyMiddleware(thunk) const storeEnhancerStoreCreator: StoreEnhancerStoreCreator storeEnhancer(createStore)const store: Store storeEnhancerStoreCreator(reducer)export default store4.根组件通过 Provider 注入 store src/index.tsx用provider将App.tsx包起来 import React from react import ReactDOM from react-dom import App from ./App import { Provider } from react-redux import store from ./storeReactDOM.render(Provider store{store}App //Provider,document.getElementById(root) )5.在组件中使用 src/somponents/Count/index.tsx import React, { FC } from react import { connect } from react-redux import { Dispatch } from redux import { AddState } from src/store/reducers/addReducer import { CombinedState } from src/store/reducers import * as types from /store/action.types// 声明参数接口 interface Props {count: numberadd: (num: number) void }// ReturnType获取函数返回值类型,交叉类型(用于多类型合并) // type Props ReturnTypetypeof mapStateToProps ReturnTypetypeof mapDispatchToPropsconst Count: FCProps (props) {const { count, add } propsreturn (divpcount: {count}/pbutton onClick{() add(5)}addCount/button/div) }// 这里相当于自己手动做了映射只有这里映射到的属性变化组件才会rerender const mapStateToProps (state: CombinedState) ({count: state.addReducer.count })const mapDispatchToProps (dispatch: Dispatch) {return {add(num: number 1) {// payload为参数dispatch({ type: types.ADD, payload: num })}} }export default connect(mapStateToProps, mapDispatchToProps)(Count)src/somponents/Name/index.tsx import React, { FC } from react import { connect } from react-redux import { Dispatch } from redux import { AddState } from src/store/reducers/addReducer import { CombinedState } from src/store/reducers import * as types from /store/action.types// 声明参数接口 interface Props {name: string }const Name: FCProps (props) {const { name } propsconsole.log(NameRerendered)return (divpname: {name}/p/div) }// name变化组件才会rerender const mapStateToProps (state: CombinedState) ({name: state.addReducer.name })// addReducer内任意属性变化组件都会rerender // const mapStateToProps (state: CombinedState) state.addReducerexport default connect(mapStateToProps)(Name)优缺点分析 优点 组件会订阅store中具体的某个属性【mapStateToProps手动完成】只要当属性变化时组件才会rerender渲染效率较高流程规范按照官方推荐的规范和结合团队风格打造一套属于自己的流程。配套工具比较齐全redux-thunk支持异步redux-devtools支持调试可以自定义各种中间件 缺点 stateactionreducer的方式不太好理解不太直观非常啰嗦为了一个功能又要写reducer又要写action还要写一个文件定义actionType显得很麻烦使用体感非常差每个用到全局状态的组件都得写一个mapStateToProps和mapDispatchToProps然后用connect包一层我就简单用个状态而已咋就这么复杂呢当然还有一堆的引入文件100行的代码用了redux可以变成120行不过换个角度来说这也算增加了自己的代码量好像除了复杂也没什么缺点了 ​ Mobx状态管理 常规使用mobx-react 使用方法 1.引入mobx yarn add mobx mobx-react -D2.创建store 在/src/store目录下创建你要用到的store在这里使用多个store进行演示 例如 store1.ts import { observable, action, makeObservable } from mobxclass Store1 {constructor() {makeObservable(this) //mobx6.0之后必须要加上这一句}observablecount 0observablename ryactionaddCount () {this.count 1} }const store1 new Store1() export default store1store2.ts 这里使用 makeAutoObservable代替了makeObservable这样就不用对每个state和action进行修饰了两个方法都可自行选择 import { makeAutoObservable } from mobxclass Store2 {constructor() {// mobx6.0之后必须要加上这一句makeAutoObservable(this)}time 11111111110 }const store2 new Store2() export default store23.导出store src/store/index.ts import store1 from ./store1 import store2 from ./store2export const store { store1, store2 }4.根组件通过 Provider 注入 store src/index.tsx用provider将App.tsx包起来 import React from react import ReactDOM from react-dom import App from ./App import store from ./store import { Provider } from mobx-reactReactDOM.render(Provider {...store}App //Provider,document.getElementById(root) )5.在组件中使用 src/somponents/Count/index.tsx import React, { FC } from react import { observer, inject } from mobx-react// 类组件用装饰器注入方法如下 // inject(store1) // observer interface Props {store1?: any } const Count: FCProps (props) {const { count, addCount } props.store1return (divpcount: {count}/pbutton onClick{addCount}addCount/button/div) } // 函数组件用Hoc方法如下本文统一使用函数组件 export default inject(store1)(observer(Count))src/components/Name/index.tsx import React, { FC } from react import { observer, inject } from mobx-reactinterface Props {store1?: any }const Name: FCProps (props) {const { name } props.store1console.log(NameRerendered)return (divpname: {name}/p/div) } // 函数组件用Hoc方法如下本文统一使用函数组件 export default inject(store1)(observer(Name))优缺点分析 优点 组件会自动订阅store中具体的某个属性无需手动订阅噢【下文会简单介绍下原理】只有当订阅的属性变化时组件才会rerender渲染效率较高一个store即写state也写action这种方式便于理解并且代码量也会少一些 缺点 当我们选择的技术栈是ReactTypescriptMobx时这种使用方式有一个非常明显的缺点引入的store必须要在props的type或interface定义过后才能使用会增加不少代码量而且还必须指定这个store为可选的否则会报错因为父组件其实没有传递这个prop给子组件这样做还可能会致使对store取值时提示可能为undefined虽然能够用“!”排除undefined可是这种作法并不优雅。 最佳实践mobxhooks 使用方法 1.引入mobx 同上 2.创建store 同上 3.导出store结合useContext src/store/index.ts import React from react import store1 from ./store1 import store2 from ./store2// 导出store1 export const storeContext1 React.createContext(store1) export const useStore1 () React.useContext(storeContext1)// 导出store2 export const storeContext2 React.createContext(store2) export const useStore2 () React.useContext(storeContext2)4.在组件中使用 无需使用Provider注入根组件 src/somponents/Count/index.tsx import React, { FC } from react import { observer } from mobx-react import { useStore1 } from /store/// 类组件可用装饰器方法如下 // observerconst Count: FC () {const { count, addCount } useStore1()return (divpcount: {count}/pbutton onClick{addCount}addCount/button/div) } // 函数组件用Hoc方法如下本文统一使用函数组件 export default observer(Count)src/components/Name/index.tsx import React, { FC } from react import { observer } from mobx-react import { useStore1 } from /store/const Name: FC () {const { name } useStore1()console.log(NameRerendered)return (divpname: {name}/p/div) }export default observer(Name)优缺点分析 优点 学习成本少基础知识非常简单跟 Vue 一样的核心原理响应式编程。一个store即写state也写action这种方式便于理解组件会自动订阅store中具体的某个属性只要当属性变化时组件才会rerender渲染效率较高成功避免了上一种使用方式的缺点不用对使用的store进行interface或type声明内置异步action操作方式代码量真的很少使用很简单有没有强烈推荐 缺点 过于自由Mobx提供的约定及模版代码很少这导致开发代码编写很自由如果不做一些约定比较容易导致团队代码风格不统一团队建议启用严格模式使用方式过于简单 ​ Mobx自动订阅实现原理 基本概念 Observable //被观察者状态 Observer //观察者组件 Reaction //响应是一类的特殊的 Derivation可以注册响应函数使之在条件满足时自动执行。建立依赖 我们给组件包的一层observer实现了这个功能 export default observer(Name)组件每次mount和update时都会执行一遍useObserver函数useObserver函数中通过reaction.track进行依赖收集将该组件加到该Observable变量的依赖中bindDependencies。 // fn function () { return baseComponent(props, ref); export function useObserver(fn, baseComponentName) {...var rendering;var exception;reaction.track(function () {try {rendering fn();}catch (e) {exception e;}});if (exception) {throw exception; // re-throw any exceptions caught during rendering}return rendering; }reaction.track() _proto.track function track(fn) {// 开始收集startBatch();var result trackDerivedFunction(this, fn, undefined);// 结束收集endBatch();};reaction.track里面的核心内容是trackDerivedFunction function trackDerivedFunctionT(derivation: IDerivation, f: () T, context: any) {...let result// 执行回调f触发了变量即组件的参数的 get从而获取 dep【收集依赖】if (globalState.disableErrorBoundaries true) {result f.call(context)} else {try {result f.call(context)} catch (e) {result new CaughtException(e)}}globalState.trackingDerivation prevTracking// 给 observable 绑定 derivationbindDependencies(derivation)...return result }触发依赖 Observable被观察者状态修改后会调用它的set方法然后再依次执行该Observable之前收集的依赖函数触发rerender。 组件更新 用组件更新来简单阐述总结一下mobx的执行原理。 observer这个装饰器也可以是Hoc对React组件的render方法进行track。将render方法加入到各个observable的依赖中。当observable发生变化track方法就会执行。track中还是先进行依赖收集调用forceUpdate去更新组件然后结束依赖收集。 每次都进行依赖收集的原因是每次执行依赖可能会发生变化 总结 简单总结了一下目前较为常用的状态管理方式我个人最喜欢的使用方式是MobxHooks简单轻量易上手。各位可以根据自己的需求选择适合自己项目的管理方式。
http://www.w-s-a.com/news/557081/

相关文章:

  • wordpress新手建站win8网站模版
  • 网站的简单布局孝感 商务 网站建设
  • 湖北手机版建站系统价格优化网站内容
  • 网站后台登录不显示验证码软文发布网站
  • 企业微网站建设方案收费的网站如何免费
  • 平昌县建设局网站中国500强企业有哪些
  • 网站开发制作的流程是什么网页打不开显示不安全怎么办
  • 网络网站开发设计安徽建设工程信息网怎么打不开了
  • 百度网站推广申请深圳公众号制作
  • 百度站长怎么做网站维护中国深圳航空公司官网
  • xampp安装网站模板海南一家天涯社区
  • 网站建设 管理系统开发仿租号网站源码网站开发
  • 怎么自己弄网站免费网站设计用什么软件
  • 网站分几种access做网站数据方法
  • 网站默认图片s001网站建设公司
  • 淘宝的电子商务网站的建设东莞哪里有网站制作公司
  • 西安网站制作怎么联系wordpress登陆界面打开慢
  • 高端工作网站网站推广seo代理
  • 一般找素材都是做哪几个网站呢推广引流工具
  • 必须做网站等级保护html网页设计题库
  • 移动端网站开发 float手机在线建网站
  • 教育网站模板下载做汽车网站开题报告的意义
  • 网站首页做后台链接昌平网站制作
  • 营销型门户网站建设浏览器下载免费大全
  • 快三网站开发推广普通话手抄报内容50字
  • 沈阳专业做网站开发公司asp网站搭建教程
  • 网站建设代码福州小程序开发平台
  • 了解做房产广告的网站手机版官方网站的建设
  • 如何与别的网站做友情链接做网站排名大概要多少钱
  • 东莞市锂电池网站建设HTML5怎么做自适应网站