合理的实践是什么样的

在大多数coding的场景下,我们习惯于自由开发。不同的代码风格造就着无数的人在coding的时候口吐芬芳。 对于上面的情况,我分享了一些最近使用reactnative和typescript进行配合开发,在搭建基础设施的时候,所产生的思考。

前言

本文不对reactnative进行过多讲解,主要以typescript为核心给我们所带来的思考:

大多数人对typescript的理解与印象,可能是说它是一个带类型的javascript,然后就没下文了。一直在那些类型给我们带来的语法糖的区域里。个人理解tyepescript的出现给我们前端带来了那些优秀的编程思想。如面向对象,ioc容器依赖注入,aop面向切面编程。基与这些我们可以搭建出一个代码结构比较健全的项目。虽说es6的出现,这些编程理念也可灵活的运用。但没法给我们带来静态类型的好处。

一、逻辑与UI分离

逻辑是什么?逻辑是一个纯类,包含属性,方法,可以继承其他类。我们所有的逻辑都应该封装到类里,不同的逻辑,分类不同类。相同逻辑可以使用依赖注入的方法,进行共享。不需要任何的展示方法(函数)

UI是什么?UI是一个函数,以react为例,hook函数来展示UI视图,这个函数只能包括,ui展示和事件绑定这些操作。复杂的逻辑尽量写到一个类里,在hook函数里导入并赋值到一个变量里进行api处理。

每次去导入的类的时候还需要new 成一个对象来进行导入。yes?

no。当然不是,这样太过麻烦,并且导入一个类的时候,还要想办法进行组件间共享数据。相同的操作我们应该封装起来。以HOC的方式对组件进行封装。

下面我会进行详细讲解。

二、reactnative是什么?

reactnatie可以使用react来开发移动原生应用,其通过react 的虚拟dom 借助于javascript core 引擎 给原生发事件通知,原生端订阅到组件的大小,位置等信息给原生组件(android ui,ios ui),最后由原生组件来渲染,从而来提高app的性能问题。当然这种渲染方式也是有弊端的,reactnaive也有相应的解决方案。

三、面向对象的编程理念

1、面向对象的三大特征

封装   继承   多态 (相信大家对于他们了解并不少,不在这里解释了)

类里面有一个很重要的概念,没错它就是构造函数constructor,进行一些初始化操作,下文 会用到。可用于依赖注入共享一些数据

import CommonStore from '../../stores/CommonStore';//导入通用类
import {injectable, autoInjectable, injectAll} from 'tsyringe';
@injectable()
class User{  name:string='德玛西亚'; //属性 constructor( public commonStore: CommonStore //构造器依赖注入 ) { super(this)}}

上面的代码没太理解没关系,接下会讲解到。

四、ioc容器依赖注入

1、ioc是什么

IOC又叫依赖注入,就是由IOC容器在运行期间,动态地将某种依赖关系注入到对象之中 就是指通过引入IOC容器,利用依赖关系注入的方式,实现对象之间的解耦。

看上图,对象A和对象B,对象之间已经没有了耦合关系,彼此毫无联系,但又通过IOC把系统中的所有对象粘合在一起发挥作用。

所以对象A里可以共享对象B的数据,看起来和对象继承很像,那多继承呢,没法在一个对象里共享多个对象,IOC容器可以

2、组件之间共享对象

上文讲到,对象间可进行依赖注入共享数据。那么问题来了,如何在hook函数组间里共享这些数据呢?有人说,直接导入对象。对,那如何导入呢。前文说过我们所有的逻辑都是类,那么导入一次,就new 一次。可以是可以,不够优雅。来,优雅一点怎么搞呢。有人还记得context对象,组件间共享数据的一种。content对象提供了一个组件provider,改组件通过value属性来注入所要共享的对象,组件provider包裹这子组件。也就是是每一个被组件provider所包裹的子组件就可以拿到注入进来的对象。ok,逻辑理清了。看如何操作。

3、使用tsyringe实现IOC

[tsyringe -> 用于TypeScript/JavaScript的轻量级依赖注入容器,用于构造函数注入。

1.封装context对象 (react提供了createContext方法来创建一个context对象)

2.本地注入store(注入共享对象)

4、封装context对象

 /*** @Description:封装context对象* @date 2022/8/31
*/
import React, { useContext } from 'react'
import invariant from 'invariant'
import type { DependencyContainer } from 'tsyringe'export const LocalStoreContext = React.createContext<any>(null)
LocalStoreContext.displayName = 'LocalStoreContext'export function useLocalStore<T>(): T {const store: T = useContext(LocalStoreContext)invariant(store, 'local store is not exist!')return store
}export const StoreContainerContext = React.createContext<DependencyContainer | null>(null)
StoreContainerContext.displayName = 'StoreContainerContext'

上面用react提供了createContext方法创建一个了普通的context对象,着重说下DependencyContainer,你可看成我们注入依赖时所需要令牌,通过createContext创建了这个实例。

5、本地注入store(注入共享对象)

/*** @Description:本地注入store* @date 2022/8/31
*/
import React, { useContext, useMemo } from 'react'
import { container, Lifecycle,InjectionToken, } from 'tsyringe'
import hoistNonReactStatic from 'hoist-non-react-statics'
import { LocalStoreContext, StoreContainerContext } from '../../until/ContextHelpers';export function withLocalStore<T extends JSX.IntrinsicAttributes, S>(WrappedComponent: React.ComponentType<T>,storeClass: { new (...args: any[]): S }
): React.ComponentType<T> {function WithLocalStoreHoc(props: T) {const superContainer = useContext(StoreContainerContext) || containerconst selfContainer = useMemo(() => {const componentContainer = superContainer.createChildContainer()if (!componentContainer.isRegistered(storeClass, false)) {componentContainer.register(storeClass,{ useClass: storeClass },{ lifecycle: Lifecycle.Singleton })}return componentContainer}, [superContainer])return (<StoreContainerContext.Provider value={selfContainer}><LocalStoreContext.Provider value={selfContainer.resolve(storeClass)}><WrappedComponent {...props} /></LocalStoreContext.Provider></StoreContainerContext.Provider>)}WithLocalStoreHoc.displayName = `WithLocalStoreHoc(${getDisplayName(WrappedComponent)})`hoistNonReactStatic(WithLocalStoreHoc, WrappedComponent)return WithLocalStoreHoc
}function getDisplayName<T>(WrappedComponent: React.ComponentType<T>) {return WrappedComponent.displayName || WrappedComponent.name || 'Component'
}

当我们使用tsyringe进行依赖注入时

1.创建一个DelayedConstructor的实例,其实就是token验证

2.注册一个共享数据(对象),这里还牵扯到单例模式,该对象只能创建为单例模式,只会有一个实例共享对象。new 的时候就数据就不会被重置。

3.DelayedConstructor对象提供了provider组件,通过value属性注入这个对象,解析着这个共享数据

4.DelayedConstructor对象提供了provider包裹着子组件,子组件间共享数据对象

5.在通过useContext hook 使用provider组件底层组件间的共享

五、使用IOC和Mobx进行合理的逻辑与UI分离

1、逻辑处理

import {observable, runInAction, makeObservable, action} from 'mobx'
import {injectable, autoInjectable, injectAll} from 'tsyringe';
import UserStore from "../../stores/UserStore";
import CommonStore from '../../stores/CommonStore';
import {UserInfo} from '../../stores/model/Uesr';@injectable()
export default class HomeStore {@observable userInfo: UserInfo | undefined;constructor( public userStore: UserStore,public commonStore: CommonStore ) {makeObservable(this)}@action.boundgetUserInfo() {this.userStore?.getInfo();this.userInfo = this.userStore?.userInfo;}}

1.使用mobx中@observable进行数据响应时处理

2.使用tsyringe的@injectable()进行依赖注解在constructor函数初始化参数的时候,传了一个类

2.UI处理

/*** @Description:主页* @date 2022/8/29*/
import {View, Text, StyleSheet, ScrollView, Animated} from 'react-native';
import React, {useContext, useRef} from 'react';
import {observer} from 'mobx-react';
import HomeStore from './homeStore';
import {withLocalStore} from '../../components/withLocalStore';
import {useLocalStore} from '../../until/ContextHelpers';
import {useMount} from 'ahooks';
import {LargeList} from "react-native-largelist";
import {ChineseWithLastDateHeader} from "react-native-spring-scrollview/Customize";interface IProps {}const HomeScreen = (props: IProps) => {const store = useLocalStore<HomeStore>();useMount(() => {store.getUserInfo();console.log('userInfo', store.userInfo?.userName)})return <View style={styles.body}> </View>
}export default withLocalStore(observer(HomeScreen), HomeStore);

1.通过封装的高阶组件withLocalStore进行组件包裹。observer是mobx提供的,可使该组件响应时监听数据的变化,视图更改。

2.通过封装useLocalStore传入一个类(依赖),得到一个可共享的对象。该对象封装所有的逻辑api处理。

总结

以上就是今天要讲的内容,本文介绍了ioc的使用及一些概念上的东西,而typescript提供了大量能使我们快速便捷开发的编程思想。对于上文有不同见解的,可以开放的进行相互学习。欢迎留言自己的不同理解。

最后

整理了75个JS高频面试题,并给出了答案和解析,基本上可以保证你能应付面试官关于JS的提问。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

Typescript的应用与思考相关推荐

  1. Typescript助力项目开发:JS切换TS、TS类型定制与思考

    TS已经成为可以帮助项目顺利开发的存在了.在上半年笔者就被要求采用TS开发新的项目,并在一些老项目中用TS去改造(因为沟通原因我以为某个远程组件只有TS版本).在其中也有了一些思考. 首先是目录结构. ...

  2. vue component created没有触发_详解在Vue中使用TypeScript的一些思考(实践)

    Vue.extend or vue-class-component 使用 TypeScript 写 Vue 组件时,有两种推荐形式: Vue.extend():使用基础 Vue 构造器,创建一个&qu ...

  3. TypeScript 从听说到入门(上篇)

    我为什么会这样念念又不忘 / 你用什么牌的箭刺穿我心脏 我也久经沙场 / 戎马生涯 / 依然 / 被一箭刺伤 --李荣浩<念念又不忘> 接下来我会分上.下两篇文章介绍 TypeScript ...

  4. 如何将三万行代码从Flow移植到TypeScript?

    作者 | David Gomes 译者 | 弯月 责编 | 郭芮 来源 |  CSDN(ID:CSDNnews) [编者按]在内存安全中,类型安全是很重要的一个命题.为了确保JavaScript项目运 ...

  5. 基于 GraphQL 实践的一点思考

    hello~亲爱的观众老爷们大家好~最近一直沉迷于 GraphQL 的应用实践,正好公司黑客马拉松临近,就拉上了两位小伙伴,结合实际的业务场景,把 GraphQL 作为中间层的解决方案提上去~项目完成 ...

  6. JavaScript前端框架的思考

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:现在JavaScript前端框架层出不穷,尤其Angular进入到2.x时候之后,我们 ...

  7. React Bind Handle的思考

    文章来自我个人的Github 在平时的开发里面,总会碰到handle绑定的问题.如果你和我一样懒或者思考过,你会觉得这个过程实在是太烦了吧.这里记录一下我的思路和历程. 这里以一个按钮的点击事件来做示 ...

  8. 我写的第一本书《TypeScript 入门教程》

    阅读原文 持续了大半年的学习和写作,在今天终于告一段落了. 写书之旅 最初有写书的想法,是刚加入微软的时候. 由于工作中需要重度使用 TypeScript,所以我花了几天的时间研读了好几遍官方手册和中 ...

  9. 知识图谱前端插件_大型前端项目可持续演进开发的思考

    引言 当谈起这个话题的时候,不得不去想到<人月神话>这本著作中所描述的软件工程思想,其中的最后一段总结论述: 软件工程的焦油坑在将来很长一段时间内会继续地使人们举步维艰,无法自拔.软件系统 ...

  10. 推荐 7 个学习 TypeScript 的宝库,2021 是时候给自己加薪了!

    大家好,新年快乐,我是你们的 猫哥,一个不喜欢吃鱼.又不喜欢喵 的超级猫 ~ 前言 猫哥是一个常年混迹在 GitHub 上的猫星人,所以发现了不少好的前端开源项目.常用技巧,在此分享给大家. 公众号: ...

最新文章

  1. 推荐一些算法方面的好书
  2. R语言效用分析 ( 效能分析、Power analysis)确定样本量、假设检验与两类错误、pwr包进行效用分析 ( 效能分析、Power analysis)的常用函数列表
  3. 周志华:“数据、算法、算力”人工智能三要素,在未来还要加上“知识”
  4. thinkphp mysql函数_php封装的数据库函数与用法示例【参考thinkPHP】
  5. 前端学PHP之面向对象系列第四篇——关键字
  6. HTML DOM Element 对象
  7. 利用Mycat中间件实现RDS MySQL的分库分表及读写分离功能
  8. 用LINQ来对文章列表进行操作
  9. command not found Operation not permitted
  10. 工业以太网交换机品牌排行榜,国产工业交换机哪个品牌好?
  11. Qt4访问sqlite数据库
  12. 42表盘直径是从哪测量_爱彼15703和15710区别在哪?背透和密底哪个更好?
  13. c语言int doubt,c语言错误error: incompatible types in assignment
  14. Android学习日志1---在AndroidStudio启动Android 模拟器(ADV)发生的失败
  15. cadence 17.2 入门学习2 allegro
  16. 背单词App开发日记3
  17. 推荐一个开源电子白板,教学专用。
  18. 通过PyFMI读取FMU文件及PyFMI的安装教程
  19. 章节三:BeautifulSoup
  20. 安全工具checksec.sh

热门文章

  1. 使用鼠标右击Gite Bash Here 将本地文件上传到 GitHub
  2. 计算机桌面左上角 鼠标,鼠标一直跑到桌面左上角怎么解决
  3. table表格实现第一列固定
  4. VC++使用管道重定向进程输入输出(附源码)
  5. 从零开始学习深度学习,推荐几本书单,建议按照先后顺序排名进行学习
  6. 台式计算机怎么安装无线网卡,台式机用无线网卡,小编教你台式机怎么用无线网卡...
  7. 超多淘宝京东抢购秒杀软,脚本,易语言软,有作者
  8. LabVIEW的编程-程序框图入门笔记
  9. SMP_WEIBO_2016 微博用户画像 可视化(未完成)
  10. 全球定位经纬度的方法现在是GPS等系统定位,以前是指南针罗盘六分仪