本人技术栈是Vue,最近调部门改成用React开发,从头开始踩坑,持续更新中~

1月18日内容汇总

记一次vue3.0技术分享会
Vue3.0 官方文档
备战2021:vite 工程化实践,建议收藏

1月14日内容汇总

如何实现一个react-router路由拦截(导航守卫)
React Router 4.0 实现路由守卫
https://segmentfault.com/a/11...
http://cache.baiducontent.com...
https://segmentfault.com/a/11...
https://segmentfault.com/a/11...
http://cache.baiducontent.com...
使用React.memo()来优化函数组件的性能

1月6日内容汇总

使用 npm install 拉取依赖的时候报错,可以试一下清空缓存,后面的参数 f 表示强制执行。

$ npm cache clean -f

1月1日内容汇总

Vue + Nuxt.js 项目推荐:
领课网络(RonCoo) / roncoo-education-web

React Redux 官方文档
React-Redux 文档 - Segmentfault

12月30日内容汇总

测试的同学提了一个老项目的缺陷,说是提交到后台的参数会把上一次操作的数据也给带上。我看了下代码,各种拼接字符串,而且他就是为了得到一个逗号分隔的字符串,还要手写 for 循环,直接调用数组的 join 或者 toString 不香吗?

修改方案:不管 nodesList 原来是不是空值,直接用一个新的值去替换;使用 map 方法生成一个节点ip的数组,调用 join 方法将数组转成字符串。

36c1c2534bc7937e2b5f0fd0990e0526.png

说明:Array.prototype.join() 或者 Array.prototype.toString() 都默认返回以逗号分隔的字符串,这里为了语义更好给 join 传了一个 "," 作为参数。如果不希望有分隔符可以使用 Array.prototype.join("")

12月29日内容汇总

注释// TODO的作用

在注释中写 // TODO,一些编辑器会进行代码高亮,例如 Android Studio,IDEA。在 vs code 中可以装一个插件 todo-tree,支持高亮显示 TODOFIXMETagDONE等注释,还可以自定义样式。
vscode 插件推荐 todo-tree

记一次vue3.0技术分享会
第二集: 从零开始实现一套pc端vue的ui组件库(icon组件)

12月28日内容汇总

今天同事问了一个问题,在前端项目中,public 和 src/asstes 都可用于存放静态资源,这两个有什么区别呢?

查了一下其实很简单,在 public 目录下的文件不会被 webpack 打包,而是直接复制一份到构建出来的文件夹中;在 src/asserts 下的文件会被打包编译(前提是在JS中有引入),从而在实际项目中减少 HTTP 请求。

在实际项目中,public还是有它的作用的。如果你希望你的文件不被编译,比如jquery.min.js,或者压缩好的js插件等,你就可以把文件放在public文件夹中,这样可以减少文件构建时间,还可以减少构建出来的文件大小。

React使用公共文件夹public

12月22日内容汇总

最近一个项目需要重构,但是那个项目不断还有新需求,给重构带来了一定难度。找了一些react后台模板,提升一下重构效率。

基于React+antd的后台管理模板(可预览)
react构建后台管理系统
React+AntD 后台管理系统解决方案 -- 终极版
使用React全家桶搭建一个后台管理系统
react中后台管理界面

12月2日内容汇总

JS 函数库

Vue 中主要使用 lodash ,React 中使用 Immutable.js
Immutable.js入门 - 知乎
为什么 react要使用immutable.js

Vue 和 React 项目多环境部署

开发环境:development
集成测试环境:staging
发布环境:production

vue-cli-service 机制

三分钟教你搞定 React 项目多环境配置 - 知乎
react----cross-env配置多环境变量
react使用docker时多环境支持
React 添加环境变量
基于create-react-app 的 webpack 配置多环境

11月30日内容汇总

React 中动态加载组件

React.lazy() 允许你定义一个动态加载的组件。这有助于缩减 bundle 的体积,并延迟加载在初次渲染时未用到的组件。

const SomeComponent = React.lazy(() => import('./SomeComponent'));
使用 React.lazy 的动态引入特性需要 JS 环境支持 Promise。在 IE11 及以下版本的浏览器中需要通过引入 polyfill 来使用该特性。

Vue 这个被称为异步组件,也是利用 Promise 来实现的。

Vue.component(
  'async-webpack-example',
  // 这个动态导入会返回一个 `Promise` 对象。
  () => import('./my-async-component')
)

当使用局部注册的时候,你也可以直接提供一个返回 Promise 的函数:

new Vue({
  // ...
  components: {
    'my-component': () => import('./my-async-component')
  }
})

React 中的 style

React 中的 style 并不是 Vue 中的双大括号,最外面那个括号代表内部是 JS 表达式,里面的括号是 JS 对象。所以多个样式之间用 , 分隔,原生的 HTML 行内样式用 ; 分隔,样式属性命名采用小驼峰法。

style 通常用来绑定动态样式,元素的主要样式应该使用外部引入的 CSS 样式表
function HelloWorldComponent() {
  return <div style={{color: blue, fontSize: 14px}}>Hello World!</div>;
}

既然 style 其实是 JS 对象,那么就可以把对象抽出来,从而实现动态样式:

const divStyle = {
  color: 'blue',
  backgroundImage: 'url(' + imgUrl + ')',
};

function HelloWorldComponent() {
  return <div style={divStyle}>Hello World!</div>;
}
在 Vue 中可以通过计算属性实现动态样式

React 会自动添加 ”px” 后缀到内联样式为数字的属性后。如需使用 ”px” 以外的单位,请将此值设为数字与所需单位组成的字符串。

// Result style: '10px'
<div style={{ height: 10 }}> Hello World! </div>

// Result style: '10%'
<div style={{ height: '10%' }}> Hello World! </div>
但并非所有样式属性都转换为像素字符串。有些样式属性是没有单位的(例如 zoomorderflex)

className 和 htmlFor

由于 classfor 都是 JS 关键字,所以在 React 里面使用 classNamehtmlFor 代替。

dangerouslySetInnerHTML

React 中使用 dangerouslySetInnerHTML 渲染 HTML,尽量不要用,容易导致 XSS 攻击。

// 需要传一个 key 为 __html 的对象
function createMarkup() {
  return {__html: 'First &middot; Second'};
}

function MyComponent() {
  return <div dangerouslySetInnerHTML={createMarkup()} />;
}
Vue 中使用 v-html 指令渲染 HTML

11月19日内容汇总

JSX 的一些注意事项

使用 JSX 必须在 React 作用域内,这样才能编译。在如下代码中,虽然 ReactCustomButton 并没有被直接使用,但还是需要导入:

import React from 'react';
import CustomButton from './CustomButton';

function WarningButton() {
     return <CustomButton color="red" />;
}

JSX 中可以使用点语法,例如:

<React.Fragment></React.Fragment>
<Form.Item></Form.Item>

自定义组件必须大写字母开头,才能被识别为 React 组件。

React 组件名不能是 JS 表达式,如果需要动态渲染组件,需要先将 组件名赋值给一个大写字母开头的变量:

import React from 'react';
import { PhotoStory, VideoStory } from './stories';

const components = {
  photo: PhotoStory,
  video: VideoStory
};

function Story(props) {
  const SpecificStory = components[props.storyType];
  return <SpecificStory story={props.story} />;
}

与 Vue 类似,React 的 props 花括号里面接受 JS 表达式:

// React 用法
<MyComponent foo={isShow ? "1" : "0"} />
// Vue 用法
<my-component :foo="isShow ? '1' : '0'" />

if 语句以及 for 循环不是 JavaScript 表达式,所以不能在 JSX 中直接使用。但是,你可以用在 JSX 以外的代码中。

React 组件通过 props 传字符串有两种做法,第一种直接通过字符串字面量:

// React 用法
<MyComponent message="hello world" />
// Vue 用法
<my-component message="hello world" />

另一种是通过表达式:

// React 用法
<MyComponent message={'hello world'} />
// Vue 用法
<my-component :message="`hello world`" /> // Vue的属性前面加上v-bind,后面的""里面就是JS表达式

React 如果没有给 props 赋值,它会有一个默认值 true

这点我觉得还是 Vue 做得好,可以手动指定 props 的默认值和类型,类型传错了还会给你警告,维护起来相当方便

React 中的 props 对象可以进行属性展开,下面两个组件是等价的:

function App1() {
    return <Greeting firstName="Ben" lastName="Hector" />;
}

function App2() {
    const props = {firstName: 'Ben', lastName: 'Hector'};
    return <Greeting {...props} />;
}

下面这个技巧非常有用,选择只保留当前组件需要接收的 props,并使用展开运算符将其他 props 传递下去:

const Button = props => {
    const { kind, ...other } = props;
    const className = kind === "primary" ? "PrimaryButton" : "SecondaryButton";
    return <button className={className} {...other} />;
};

高阶组件

高阶组件在 React 官方文档的说法是用于替代 mixins 实现组件方法复用。

高阶组件是参数为组件,返回值为新组件的函数

也就是说在组件外面封装了一层,把可以复用的方法都抽出来。

我看了一下文档的示例代码,觉得高阶组件的场景和 mixins 其实还是有区别的,而且 mixins 是可以全局混入的。文档上的示例我觉得更接近于 Vue 中的动态组件。

function withSubscription(WrappedComponent, selectData) {
  // ...并返回另一个组件...
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.handleChange = this.handleChange.bind(this);
      this.state = {
        data: selectData(DataSource, props)
      };
    }
    componentDidMount() {
      DataSource.addChangeListener(this.handleChange);
    }
    componentWillUnmount() {
      DataSource.removeChangeListener(this.handleChange);
    }
    handleChange() {
      this.setState({
        data: selectData(DataSource, this.props)
      });
    }
    render() {
      return <WrappedComponent data={this.state.data} {...this.props} />;
    }
  };
}

使用的时候把组件传递给 withSubscription() :

const CommentListWithSubscription = withSubscription(
  CommentList,
  (DataSource) => DataSource.getComments()
);

const BlogPostWithSubscription = withSubscription(
  BlogPost,
  (DataSource, props) => DataSource.getBlogPost(props.id)
);

之前不理解React 路由为什么要这样写,现在明白了,这其实就是高阶组件:

const NavbarWithRouter = withRouter(Navbar);

Vue 动态组件的 is 属性也可以接收一个组件作为参数,同时也能传递 props

<component :is="currentTabComponent" :values="values"></component>

11月18日内容汇总

React 组件生命周期调用顺序

挂载

组件实例被创建并插入DOM
  • constructor()
  • static getDerivedStateFromProps()
  • render()
  • componentDidMount()

更新

当组件的 props 或 state 发生变化时会触发更新
  • static getDerivedStateFromProps()
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate()
  • componentDidUpdate()

卸载

当组件从 DOM 中移除时会进行调用
  • componentWillUnmount()

错误处理

当渲染过程,生命周期,或子组件的构造函数中抛出错误时会进行调用
  • static getDerivedStateFromError()
  • componentDidCatch()

更多内容参考:
常用生命周期方法

2.x 的生命周期函数与新版 Composition API 之间的映射关系:

  • beforeCreate -> 使用 setup()
  • created -> 使用 setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured

注意:beforeCreatecreatedVue3 中已经由 setup 替代。

参考资料

Vue 3.0 有很多借鉴了 React 的地方,看了 React 文档之后 可以对比着看下 Vue 3.0 。

Vue 3.0 修炼手册
抄笔记:尤雨溪在Vue3.0 Beta直播里聊到了这些…
API 手册 - Vue 组合式 API

Koa 快速入门系列

【从前端到全栈】- koa快速入门指南
【进阶篇】koa+Mysql的全栈之旅
【全栈之旅】NodeJs登录流程以及Token身份验证

11月17日内容汇总

React Hooks的用法

函数组件有重大限制,必须是纯函数,不能包含状态,也不支持生命周期方法。React Hooks 的设计目的,就是加强版函数组件,完全不使用"类",就能写出一个全功能的组件。

四个常用Hooks

useState()
useContext()
useReducer()
useEffect()

useState() 用于为函数组件引入状态(state)。纯函数不能有状态,所以把状态放在钩子里面。

import React, { useState } from "react";

export default function  Button()  {
  const [buttonText, setButtonText] = useState("Click me,   please");

  function handleClick()  {
    return setButtonText("Thanks, been clicked!");
  }

  return  <button  onClick={handleClick}>{buttonText}</button>;
}

useEffect()用来引入具有副作用的操作,最常见的就是向服务器请求数据。以前,放在componentDidMount里面的代码,现在可以放在useEffect()

useEffect(()  =>  {
 // 这里调接口
}, [dependencies])

useEffect() 接受两个参数。第一个参数是一个函数,异步操作的代码放在里面。第二个参数是一个数组,用于给出 Effect 的依赖项,可以省略。组件第一次渲染时, useEffect() 就会执行。当依赖项的数组发生变化, useEffect() 也会执行。

Vue 3.0 的 Composition API 借鉴了 React Hooks

轻松学会 React 钩子:以 useEffect() 为例 - 阮一峰
React Hooks 入门教程 - 阮一峰

React中Fragment的用法

与 Vue 类似, React 组件要求 return 的内容必须由唯一根元素包裹,否则就会报错。

如果希望在不额外创建DOM元素的情况下 return 多个元素,就可以用到Fragment。

render() {
  return (
    <React.Fragment>
      Some text.
      <h2>A heading</h2>
    </React.Fragment>
  );
}
Vue 中的 template 也是虚拟元素,但还是有区别
在 template 中的元素必须要唯一根元素包裹
template 仅仅只是在条件渲染的时候可以不用引入新的DOM元素
Vue 3.0 中也提供了类似 React 的 Fragment

Fragment还有一种简写语法 <></> 。<React.Fragment>可以接受键值或者属性,例如在列表渲染的时候绑定 key ,但是 <></> 不行。

render() {
  return (
    <>
      Some text.
      <h2>A heading</h2>
    </>
  );
}

另外react 16开始, render支持返回数组,可以减少不必要的节点嵌套。

export default function () {
    return [
        <div>1</div>,
        <div>2</div>,
        <div>3</div>
    ];
}
Vue 3.0 的 render 函数同样也支持返回数组

Fragment - React中文文档

组件继承的两种写法

以上面的Fragment为例,如果只引入 React ,那么使用就要像这样 <React.Fragment>

import React from "react";

function App() {
    return (
        <React.Fragment>
            {/* Some text here */}
        </React.Fragment>
    )
}

如果像下面这样引入,就可以像这样使用 <Fragment>

import React, { Fragment } from "react";

function App() {
    return (
        <Fragment>
            {/* Some text here */}
        </Fragment>
    )
}

严格模式

嵌套在 <StrictMode> 标签中的元素将开启严格模式,用来突出显示应用程序中潜在问题。与 Fragment 一样,StrictMode 不会渲染任何可见的 UI。它为其后代元素触发额外的检查和警告。

严格模式检查仅在开发模式下运行;它们不会影响生产构建
import React from 'react';

function ExampleApplication() {
  return (
    <div>
      <Header />
      <React.StrictMode>
        <div>
          <ComponentOne />
          <ComponentTwo />
        </div>
      </React.StrictMode>
      <Footer />
    </div>
  );
}

React’s diff algorithm

11月16日内容汇总

React事件类型

输入框:onChange,onKeyUp
按钮:onClick

React监听回车事件

<Input placeholder="www.chao99.top" onKeyUp={this.onKeyup} />
onKeyup(e) {
    if(e.keyCode === 13) {
        this.handleBtnClick()
    }
}

报错信息

Cannot update during an existing state transition (such as within render)

这个一般是事件处理函数的 this 没有绑定导致的 。

报错信息

Failed prop type: You provided a value prop to a form field without an onChange handler. This will render a read-only field.

受控组件表单必须要绑定 onChange 事件,否则这个表单就是只读,无法修改。

不能修改的前提是 value 被赋了一个常量。如果将空值 null 赋给 value ,还是可以修改的。

受控组件:自身的value值由组件的state托管,这也是 React 官方推荐的。

<Input value={this.state.name} onChange={this.handleChange} />

上面的代码中, value 用来给表单赋值, onChange 事件用于触发事件处理函数修改 state 。在 Vue 中直接就是一个语法糖 v-model

Vue 中的 <input v-model="searchText"> 等价于
<input :value="searchText" @input="searchText = $event.target.value">

非受控组件:value由第三方库或者DOM进行托管。

<Input type="file" ref={this.input}/>

文件上传是典型的非受控组件。

React修改antd原生样式

在 Vue 中直接修改是不生效的,需要通过样式穿透 >>>::v-deep

在 React 里面,调出控制台找到组件对应的类名,然后在样式文件中直接修改就行。

React修改Antd组件样式的方法


一杯绿茶
199 声望17 粉丝

人在一起就是过节,心在一起就是团圆