Skip to main content

4 posts tagged with "react"

View All Tags

组件化的 CSS

· One min read
Lex
Front End Engineer @ Baoxiaohe

Why#

传统 CSS 的书写方式已然不适合主流前端框架盛行的组件化开发。 组件化下的 CSS 应该符合以下条件👇

  • 可以编写局部CSS:具备独立作用域,不污染其他组件内样式
  • 可以编写动态CSS:可以获取当前组件的一些状态,根据状态变化生成不同的 CSS 样式
  • 支持所有的 CSS 特性:伪类、动画、媒体查询等

当然,符合原生 CSS 编写逻辑也非常重要。

How#

React 里写 CSS 并不像 Vue 那样有统一的标准,所以催生出各种各样的写法和CSS库。

内联样式#

优势

  • 样式之间不会有冲突
  • 可以动态获取当前state中的状态 缺点
  • 要使用驼峰标识
  • 代码混乱
  • 不兼容所有特性(伪类/伪元素)
Live Editor
Result
SyntaxError: Unexpected token (1:8)
1 : return ()
            ^

普通 CSS#

.css作为后缀的文件,然后再引入,很熟悉的方式。 问题就是这样的样式是全局样式,不能生成组件局部样式,权重大的标签会层叠权重小的样式。

CSS Modules#

使用很简单,像使用普通 CSS 一样导入即可。关键在于使用.module.css作为文件名后缀,并在导入时取 name what ever you want,命中className时通过name.className.

import styles from "./index.module.css";
<div className={styles.buttons}>  <Link    className="button button--secondary button--lg"    to="/docs/intro"  >    🌌 Start with Tutorial  </Link></div>

css modules 解决了局部作用域的问题,同时也有一些问题✍

  • 不能使用连接符(item-title),这在JavaScript中不被识别,需要使用驼峰命名
  • 不方便动态修改某些样式,仍然需要使用内联样式

CSS-in-JS#

CSS-in-JS 是一种模式,CSS 由 JavaScript 生成而不是在外部文件中定义。这样,All in JS 就成了🤷‍♀️。 当然,这样的开发模式并不受到所有开发者的追捧: Stop using CSS in JavaScript for web development

styled-components && emotion

That's all👏

The setState in React

· 2 min read
Lex
Front End Engineer @ Baoxiaohe

What#

在使用 React 时,并不能通过直接修改state里的数据使页面发生更新。React 没有像 Vue 一样使用Object.defineProperty或者 Proxy 的方式来监听数据变化。所以必须通过 setState方法告知 React 数据已经发生了更改。

该方法是从 Component 继承来的,源码中有具体实现。

异步更新#

异步更新很好理解,

this.state = {  message: "Hello World"}// ...this.setState({  message: "Hello React"})console.log(this.state.message) // Hello World

虽然已经告知 React 数据更新了,log 结果仍然是更新前的 message。这就是因为setState 是非同步的。

Why is setState asynchronous#

  • 显著提高性能
  • 使props和state保持同步
每次调用 setState 方法同步调用 render 函数重新渲染页面效率是很低的,最好是在获取多次 更新后批量 `render`。

U can know more in here

How get synchronized data#

  • 1、get it in callback function
this.setState({  message: "Hello React"},() => {  console.log(this.state.message) // Hello React})
  • 2、use lifecycle function 当调用render function 执行完后会回调 componentDidUpdate这个生命周期函数。👇
componentDidUpdate() {  console.log(this.state.message) // Hello React}

了解更多lifecycle function

Must setState be asynchronous#

  • 在组件生命周期或 React 合成事件(onClick)中,setState是异步;
  • setTimeout或原生 DOM 事件中,setState是同步🕵️‍♂️
changeText() {  setTimeout(() => {    this.setState({      message: "你好呀,李银河"    })    console.log(this.state.message) // 你好呀,李银河  }, 0)}
componentDidMount() {  const btnEl = document.getElementById("btn")  btnEl.addEventListener('click',() => {    this.setState({      message: "你好呀,李银河"    })    console.log(this.state.message) // 你好呀,李银河  })}

React 源码中对这两种情况进行了判断,从而导致不同的处理方式。

数据合并#

setState函数传入对象作为参数,为什么新的对象不对旧对象完全覆盖,而只是修改了同名属性。 其实是因为源码中使用了Object.assign() 函数。

// Object.assign({},prevState,partialState)Object.assign({},this.state,{message: "你好呀,李银河"})

Why should not change state#

React 明确说明不推荐在 setState 中对 state 原数据(通常是引用类型)进行修改。 原因在于性能优化(或者 extends PureComponent)时会有问题🕵️‍♂️

shouldComponentUpdate(newProps, newState) {  // 修改相同引用类型(Array)数据并不会走下行逻辑  if(newState.books !== this.state.books){    return true   }  return false}

That's all