从 loading 的 9 种写法谈 React 业务开发

栏目: IOS · Android · 发布时间: 5年前

内容简介:这是一篇比较全面讲解 React 的文章,里面很多基础知识希望你自己一边查阅资料一边学习。全文从业务开发中最常用见 loading 效果不同是实现讲起,说下现在前端开发在业务上应该有的思考。最简单的实现,我们在 Loading 组件内部声明一个状态,通过代码逻辑判断 loading 效果的展示。

这是一篇比较全面讲解 React 的文章,里面很多基础知识希望你自己一边查阅资料一边学习。全文从业务开发中最常用见 loading 效果不同是实现讲起,说下现在前端开发在业务上应该有的思考。

入门级操作

State

最简单的实现,我们在 Loading 组件内部声明一个状态,通过代码逻辑判断 loading 效果的展示。

export default class extends Component {
  ...
  render() {
    return this.state.loading ? <div className="loader" /> : <div>finish</div>;
  }
}
复制代码

完整演示

Props

随着业务的发展,这个 Loading 组件用到的地方会非常多,上面这个代码耦合了很多逻辑,为了让这个组件能够很好的复用,那我们抽离出组件的业务逻辑,将内部状态进行提升,那这个组件就是一个能被复用的 UI 组件。

export default function(props) {
  return props.loading ? <div className="loader" /> : <div>finish</div>;
}
复制代码

完整演示

注:上面两段代码你可能会想,为什么 FuncClass 都能实现一个组件,他们有什么差别吗? 其实你在开发时不容易感觉到差别,但 React 本身是进行了很多差别处理,如果是 Class 类,React 会用 new 关键字实例化,然后调用该实例的 render 方法,如果是 Func 函数,React 会直接调用它。

Refs

如果你是一个 jQuery 转型 React 的开发,会很自然的想到,我找到 Loading 组件的节点,控制他的显示与隐藏,当然这也是可以的,React 提供 Refs 方便你访问 DOM 节点 或 React 元素。

export default class extends Component {
  componentDidMount() {
    fetch().then(() => {
      this.el.changeLoading(false);
    });
  }

  render() {
    return (
      <Loading ref={el => { this.el = el; }} />
    );
  }
}
复制代码

完整演示

通用逻辑抽离

当你的应用做到一定的复杂度,不同的页面都会有 loading 效果,你肯定不希望每个页面都重复的书写一样的逻辑,这样会导致你的代码重复且混乱。

React 中有两个比较常见的解决方案 HOCRender Props ,其实这两个这两个概念都是不依赖 React 的。

让我们暂时忘掉 React,下面我对 HOCRender Props 写两个例子,你会发现组件复用是如此简单。

HOC

HOC 其实就是一种装饰器模式,它接受一个组件作为参数,然后返回相同的组件,这样就可以额外增加一些功能。

const func = () => {
  console.log("func");
};

const wrap = func => {
  console.log("wrap");
  return func;
};

// wrap 逻辑已被复用
wrap(func)();
复制代码

完整演示

Render Props

Render Props 就是我们给一个函数传递一个回调函数做为参数,该回调函数就能利用外面函数的执行结果做为参数,执行任何操作。

const func = param => {
  console.log("func");
};

const wrap = (param, func) => {
  console.log("wrap");
  func(param);
};

// wrap 逻辑已被复用
wrap("", func);
复制代码

完整演示

相同点:

重用组件逻辑
回调地狱

不同点:

  • HOC 和 父组件有相同属性名属性传递过来,会造成属性丢失;
  • Render Props 你只需要实例化一个中间类,而 HOC 你每次调用的地方都需要额外实例化一个中间类。

总的来说,在需要复用组件逻辑的时候,我个人更倾向于 Render Props 的方式。

复杂状态管理

当你的应用越来越大,组件之间交互越来越复杂,那整个页面的数据逻辑将变得难以管理,这时候为了方便管理应用的状态,你可以选择一些状态管理工具,例如 ReduxFluxdva 等。

Redux

从 loading 的 9 种写法谈 React 业务开发

我不太想谈这些数据流框架,因为他们的概念 actionstoredispatch 太过于生涩难懂。 现代前端框架 React 和 Vue 其实都是一个套路,通过数据渲染试图,然后视图上操作反过来更新数据,重新渲染视图,刷新页面。 数据叫做 store ,动作叫做 ation ,触发行为叫 dispatch ,然后数据到视图的渲染由 React/Vue 处理的。

(图片来自这里)

// reducers.js
const initialState = {
  loading: false
};

export default function reducer(state = initialState, action) {
  switch (action.type) {
    case "CHANGE_LOADING":
      return {
        loading: action.payload
      };
    default:
      return state;
  }
}
复制代码

完整演示

Saga

当你代码中有大量的异步操作时,例如 fetch 请求,你肯定会想到 事件监听回调函数发布/订阅 。 很好,上一个例子其实就是 事件监听 的处理方式,然后 回调函数 的主流的解决方案是 redux-thunk ,而 发布/订阅 的主流解决方案是saga。

import { takeLatest, put } from "redux-saga/effects";

import fetch from "./fetch";

function* fetchInfo(action) {
  yield put({
    type: "CHANGE_LOADING",
    payload: true
  });

  yield fetch();

  yield put({
    type: "CHANGE_LOADING",
    payload: false
  });
}

export default function* fetchSaga() {
  yield takeLatest("FETCH_REQUEST", fetchInfo);
}
复制代码

完整演示

当你耐心看到这里,我知道你对 React 肯定有一定的经验,现在还可以做很多,例如把 loading 状态提升到 Store 的顶部,那整个站点就只有一个 loading 了,然后你还可以将 fetch 再封装一个 HOC 修改 loading 状态,这就是一个相对完美的 loading,其实 React 业务开发都可以用这个套路。

新的 API

Context

从 loading 的 9 种写法谈 React 业务开发

上面 redux 的例子是不是过于复杂 对于简单的业务,虽然有很多页面,嵌套层次也很复杂,你当然可以不用状态管理工具,你可以试着使用 Context,它可以方便你传递数据,它其实就是 Render Props 的一种实现。

export default React.createContext({
  loading: false,
  changeLoading: () => {}
});
复制代码

完整演示

Hooks

写到这,静一下,是不是哪里做错了什么?

我的业务只是想写个简单的 loading 效果,却了解了一堆组件生命周期的概念。

Hooks 刚好帮你解决了这样的问题,Hooks 能允许你通过执行单个函数调用来使用函数中的 React 功能,让你把 面向生命周期编程 变成 面向业务逻辑编程

import React, { useState, useEffect } from "react";

import Loading from "./Loading/index";
import fetch from "./fetch";

function App() {
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch().then(() => {
      setLoading(false);
    });
  }, []);

  return <Loading loading={loading} />;
}

export default App;
复制代码

完整演示

好好总结

上面对每个点都做了具体实现,但他们都不是隔离的,你可以根据你的认知和业务特点总结抽象一套自己的方法论;

多了解多抽象多思考 ,练就十八般武艺,遇到问题的时候才能游刃有余;

React 现在宣传的东西越来越多,你最好先深入了解他们,然后用批判的眼光,保持理智,防止自己每天用很新的特性重构你自己的代码。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

文本上的算法——深入浅出自然语言处理

文本上的算法——深入浅出自然语言处理

路彦雄 / 人民邮电出版社 / 2018-3-1 / 69.00元

本书结合作者多年学习和从事自然语言处理相关工作的经验,力图用生动形象的方式深入浅出地介绍自然语言处理的理论、方法和技术。本书抛弃掉繁琐的证明,提取出算法的核心,帮助读者尽快地掌握自然语言处理所必备的知识和技能。本书主要分两大部分。第一部分是理论篇,包含前3章内容,主要介绍一些基础的数学知识、优化理论知识和一些机器学习的相关知识。第二部分是应用篇,包含第4章到第8章,分别针对计算性能、文本处理的术语......一起来看看 《文本上的算法——深入浅出自然语言处理》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码