Better

Ethan的博客,欢迎访问交流

ARTS 打卡第十一周

本次打卡值得关注的内容有,算法题比较简单就不多说了,Share 主要内容为写出干净的可伸缩的JavaScript 代码的 12 个技巧,Tips 内容主要讲述在 React 中使用 Refs 的场景,分享的内容为上一篇博客,关于代码重构的一点思考。

Algorithm

本周继续完成 easy part,名为 Search Insert Position,查询指定元素应该插入的位置,如果数组中已经存在该元素,则直接返回对应下标。

比较简单,就不废话了,直接贴代码

var searchInsert = function(nums, target) {
    for(var i = 0; i < nums.length; i++) {
        var value = nums[i];
        if(target <= value) {
            return i;
        }
    }
    return nums.length;
};

Review

本周阅读的原文来自 JavaScript Weekly 推荐,原文地址12 tips for writing clean and scalable JavaScript,说的是写出干净的可伸缩的JavaScript 代码的 12 个技巧。

词汇学习

  • evolve 进化
  • fledged 成熟的
  • tricky 复杂的
  • mediocre 平庸的
  • eventually 最终地
  • incredibly 不可思议的
  • threshold 开端
  • cluttered 混乱

12 个技巧

  • Isolate your code:隔离你的代码
    • 功能单一:一个函数只能有一个目的,且不能同时做多件事情
    • 避免造成副作用,你不能改变任何定义在你函数外部的东西,也就是纯函数,你应该通过参数接受数据,其他任何数据都是不能访问的,如果需要得到数据,使用 return 返回新值
  • modularization:模块化
  • Prefer multiple parameters over single object parameters
    • 理由就是你通过函数定义就快速明确的知道你需要给函数传递什么数据
    • 如果不这样做,当函数体变大时,由于参数嵌套在对象之中,找到需要传递哪些数据会花费你更多的时间
    • 当然,如果你函数入参过多,还是应该使用对象参数
    • 还有一个原因就是说,参数需要按照一定的顺序,如果有可选参数,需要传递 undefinednull 值,使用对象参数,顺序和 null 值就不需要关心了
    • 关于这一点,评论区有争议,其实懂的作者的目的之后,自己看场景选择即可
  • Destructuring:使用解构赋值
    • 如果使用对象作为参数,此时函数入参也可以使用解构赋值,可以帮助我们快速知道需要哪些参数
  • Use default values:使用默认参数
  • Data scarcity:数据稀少
    • 不要传递你不需要的数据
    • 提高代码可读性
  • Line and indentation limit:行数和缩进限制
    • 作者倾向于文件控制在 100 行内,有时候 200-300,极少数情况会到 400 行。我只能说 amazing!
    • 拆解文件是一种功底的表现
  • Use prettier:使用 prettier 格式化代码
  • Use meaningful variable names:使用有意义的变量名称,这个老生常谈了
    • Functions 动词短语
    • Arrays 使用 s 结尾
    • Booleans 使用 ishas 打头
    • Array functions 回调函数中也需要起有意义的名称
    • id:建议 id 也要带上类型,即 typeId
  • Use async / await where possible
  • Module import order 模块导入顺序
  • Get rid of console 清理 console

React 模块导入顺序例子

// 3rd party packages
import React from 'react'
import styled from 'styled-components'

// Stores
import Store from '~/Store'

// reusable components
import Button from '~/components/Button'

// utility functions
import { add, subtract } from '~/utils/calculate'

// submodules
import Intro from './Intro'
import Selector from './Selector'

Tip

本周分享的内容是 React 中使用 Refs 的场景和使用方式

使用 Refs 情景

  • 与第三方 DOM 集成
  • 触发命令式动画
  • 管理焦点、文本选择媒体播放

官方文档中提到:避免使用 refs 来做任何可以通过声明式实现来完成的事情

使用 refs 的几种方式

  • React.createRef()
  • 回调引用(callback refs)
  • String ref(已过时)
  • 转发 refs(Forwarding refs)

createRef 代码示例

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    // 通过 this.firstRef.current 就可以访问到当前 dom 元素了
    this.firstRef = React.createRef();
  }
  render() {
    return <div ref={this.firstRef}></div>
  }
}

Refs 回调

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
  }
  render() {
    // this.refNode 就是真实 dom 元素
    return <div ref={node => this.refNode = node}></div>
  }
}

String ref 已过时,看到别人代码这么写,知道缘由就行

// this.refs.textInput 就是真实 dom 元素
<input type="text" ref="textInput" />

转发 refs,将 ref 通过组件传递给其子节点的技术,对于可复用组件库和高阶组件等情况非常有用

const TextInput = React.forwardRef((props, ref) => (
  <input type="text" ref={ref} />
))
class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.inputRef = React.createRef();
    // 通过 this.firstRef.current 就可以访问到当前 dom 元素了
  }
  render() {
    return (
      <div>
        <TextInput ref={this.inputRef} />
      </div>
    )
  }
}

转发 refs 和高阶组件

const Input = InputComponent => {
  const forwardRef = (props, ref) => {
    const onType = () => console.log(ref.current.value);
    return <InputComponent forwardedRef={ref} onChange={onType} {...props} />
  }
  return React.forwardRef(forwardRef)
}
const TextInput = ({forwardedRef, children, ...rest}) => (
  <div>
    <input ref={forwardedRef} {...rest} />
    {children}
  </div>
)
const InputField = Input(TextInput);
class CustomTextInput extends Component {
  render() {
    const inputRef = React.createRef();
    return <InputField ref={inputRef} />
  }
}

Share

本周分享:前端组件拆分重构的思考



留言