🔥🔥🔥 原来在字节写代码就是这么朴实无华!🔥🔥🔥

前言

来到字节快一年了,最初的我满怀憧憬,以为大厂的代码一定是高深莫测、充满黑科技的艺术品。然而,深入项目后才发现,这里的代码并没有想象中那么"高大上",反而透着一股朴实无华的实用主义!

今天主要说说这些朴实无华的实用主义!

往期精彩推荐

正文

朴实无华的内联原则

首先,我先来说说第一次提交 MR 请求时,RV 的最多的问题:请用内联!

我以前的强迫症习惯(零散示例)

以前的习惯:常量必须放文件顶部!函数必须定义变量!

jsx 复制代码
import React from 'react';
import { Button, Form, Select } from "@arco-design/web-react";

const sameOptions = [
  { value: 'apple', label: 'Apple' },
  { value: 'banana', label: 'Banana' },
  { value: 'cherry', label: 'Cherry' },
];

const FormSelect = () => {
  const [form] = Form.useForm();
  const submit = () => console.log(form.getFiledsValue());
  
  return (
    <Form form={form}>
      <Form.Item label="samelabel" field="same">
        <select options={sameOptions} />
      </Form.Item>
      <Form.Item >
        <Button onClick={submit}></Button>
      </Form.Item>
    </Form>
    
  );
};

export default FormSelect;

这种方式看似简洁,但在大项目中,文件多了,变量散了,容易造成"阅读障碍"。

现在,看内联方式

内联方式(朴实示例)

jsx 复制代码
import React from 'react';
import { Button, Form, Select } from "@arco-design/web-react";

const FormSelect = () => {
  const [form] = Form.useForm();
  return (
    <Form>
      <Form.Item label="samelabel" field="same">
        <select
          options={[
            { value: 'apple', label: 'Apple' },
            { value: 'banana', label: 'Banana' },
            { value: 'cherry', label: 'Cherry' },
          ]}
        />
      </Form.Item>
      <Form.Item >
        <Button onClick={() => console.log(form.getFiledsValue())}></Button>
      </Form.Item>
    </Form>
    
  );
};

export default FormSelect;

这种代码更紧凑,一眼就能看懂逻辑。不用来回翻看跳转!日常维护也更容易一些!

当然,不是无脑内联,如果包含函数很复杂的计算,还是要求定义变量,因为每次 render 都进行复杂的计算,会导致页面卡顿!

朴实无华的变量

还一个容易出现零散问题的地方:定义变量!

我以前的习惯

js 复制代码
const App = () => {
  const [a, setA] = useState(0);
  const [b, setB] = useState(0);
  const [c, setC] = useState(0);
  
  const onAchange = (val) => setA(val);
  const onBchange = (val) => setB(val);
  const onCchange = (val) => setC(val);

  return <></>
}

相信很多小伙伴都会这么写变量吧,但是这种在我们组是很难被通过的代码,因为同样会导致找不到变量在哪的情况!

我们组的方案,是使用了一个 useSetStatehook 定义,它返回常用的 state 还会返回一个 ref state

先看看现在的写法吧!

现在的习惯

js 复制代码
const App = () => {
  const {
    state,
    setRefState,
    getRefState
  } = useSetState({
    a: 0,
    b: 0,
    c: 0
  })
  
  const onChange = (a, b, c) => setResState({ a, b, c })
  
  return <></>
}

这么写的好处,除了前面说到的变量在一块,方便查找外,还额外提供了 ref state ,如果页面仅仅是读取状态,那么可以使用它来减少无意义的页面渲染!

html 复制代码
<div>{getRefState().a}</div>

朴实无华的中间量和函数定义

另外一个 RV 的出现多次问题,就是因为我使用了 useCallback 还有 useMemo

其实当如入职,组里的新手指引里,明确写了尽量不要使用他们,但是我写项目的时候还是用了,结果就是卡在这里无法通过 Merge !

js 复制代码
const App = () => {
  const { state } = useSetState({})
  
  // 不要使用 useMemo
  const d = state.a + state.b;
  // 不要使用 useCallback
  const onChange = (val) => {
    /**todo**/
  }
  
  return <></>
}

朴实无法的组件定义

另外,给我很大震撼的是,我刚刚接手项目,一个文件居然放了好几个小组件和一个页面组件!

慢慢了解后才知道,原来是这样的:

  • 1. 如果其他地方没有用到,不允许拆封组件(内联原则)
  • 2. 一个页面的组件在多个地方使用才拆封组件,不考虑以后
  • 3.一个页面的功能组件,尽量保留在一个文件里(不过度拆封文件)

具体的例子就不展示了,但是表达的意思就是:不要过度组件化、多文件化!

朴实无华的数据与 UI 的分离

大厂项目强调可复用性,尤其是大型模块。数据逻辑(如 API 调用、状态管理)和 UI 渲染(如组件布局)如果耦合太紧,复用起来就麻烦。

关于状态分离,也有要求:没有跨页面跨模块的逻辑和 UI 没必要分离!

因为会破坏阅读代码的流畅性!

如果分离,我们组有专门的高阶组件工具!

下面是示例:

js 复制代码
import { createStore } from "@/utils";
import { useSetState } from "@/hooks";

import { useState } from "react";
export const useMaterialStore = () => {
  
 const {
    state,
    setRefState,
    getRefState
  } = useSetState({
    a: 0,
    b: 0,
    c: 0
  })
  return {
    state,
    d: get () => state.a + state.b,
    setRefState,
    getRefState
  };
};

export const {
  useStore,
  withStoreProvider
} = createStore(useMaterialStore);
js 复制代码
import {
  withStoreProvider,
  useStore
} from "./store";
import Other fron "./Other.tsx"
const Index = () => {
  const { state, d } = useStore();
  return <Other />;
};

export default withStoreProvider(Index);

这样,Index 下的任意组件都可以使用 useStore 共享数据了!

UI 组件只需订阅 useStore,逻辑复用更灵活。

下面是我自己实现的 createStore:

javascript 复制代码
import React, { createContext, useContext } from "react";
import type { PropsWithChildren, ReactNode } from "react";

export function createStore<TStore>(initializer: () => TStore) {
  const StoreContext = createContext<TStore>({} as TStore);

  // Provider 组件
  function StoreProvider({ children }: { children: ReactNode }) {
    const store = initializer();
    return 
      <StoreContext.Provider
        value={store}
      >{children}</StoreContext.Provider>
  }

  // Hook:获取 store
  function useStore(): TStore {
    const store = useContext(StoreContext);
    if (!store) {
      throw new Error("useStore must be used within a StoreProvider");
    }
    return store;
  }

  // 高阶组件:自动包裹 Provider
  function withStoreProvider(
    Component: (props: unknown) => ReactNode
  ): React.FC<PropsWithChildren> {
    return function (props: unknown) {
      return <StoreProvider>{Component(props)}</StoreProvider>;
    };
  }

  return { useStore, withStoreProvider };
}

最后

在字节写代码,就是这么朴实无华且枯燥!而且还有很多实用的小技巧,有时间我在分享给大家!

今天的分享就这些了,感谢大家的阅读!如果文章中存在错误的地方欢迎指正!

往期精彩推荐

相关推荐
豆苗学前端4 分钟前
vue3+TypeScript 实现一个图片占位符生成器
前端·面试·github
neon12045 分钟前
Vue 3 父子组件通信核心机制详解:defineProps、defineEmits 与 defineExpose 完全指南
前端·javascript·vue.js·前端框架
Ciito11 分钟前
vue+moment将分钟调整为5的倍数(向下取整)
javascript·vue.js
Juchecar22 分钟前
Vue3 开发环境搭建及循序渐进学习指南
前端·javascript
Data_Adventure38 分钟前
@scqilin/phone-ui手机外观组件库
前端
一点一木1 小时前
Vue Vapor 事件机制深潜:从设计动机到源码解析
前端·vue.js·vapor
FSHOW1 小时前
记一次开源_大量SVG的高性能渲染
前端·react.js
小牛.7931 小时前
Web第二次作业
前端·javascript·css
二闹1 小时前
都2025了还要用Layui做下拉控件-我只能说你有水平
前端
Pikachu8031 小时前
揭秘 tyarn:一个为大型 TypeScript Monorepo 优化的 Yarn 性能猛兽
前端·javascript