React系列之框架特点和组件类型

文章目录

React

MVC MVP MVVM

Web设计模式,通过分离模块来改进代码的组织方式。

MVC 是 Model View Controller 的缩写。

  • Model:模型层,数据相关的操作。
  • View:视图层,用户界面渲染逻辑。
  • Controller:控制器,数据模型和视图之间通信的桥梁。

MVC 模型把视图渲染和数据处理做了隔离,通过控制器接收视图操作,传递给数据模型,数据处理后由数据模型驱动视图渲染。

MVP 是 Model View Presenter 的缩写,可以说是 MVC 模式的改良。

  • Model、View依然负责数据和视图

如果 Model 只想做数据相关的操作,把通知 View 的逻辑挪到了 Control 里,这时 Control 摇身一变称为了 Presenter。因为解耦了 Model 和 View,也使得它们的职责划分更加清晰。

MVVM 是 Model View - ViewModel 的缩写,ViewModel 主要靠 DataBinding 把 View 和 Model 做了自动关联,框架替应用开发者实现数据变化后的视图更新。

MVVM与MVC最大的区别:实现了View和Model的自动同步,也就是当Model的属性改变时,我们不用再自己手动操作Dom元素,来改变View的显示,而是改变属性后该属性对应View层显示会自动改变。

React 并不是严格意义上 MVC MVVM 这种前端架构模式,它更像一种视图层的库。在传统的 MVC、MVP、MVVM 等架构模式中,通常会将应用程序的逻辑分成不同的部分,比如模型(Model)、视图(View)和控制器(Controller)、展示器(Presenter)或视图模型(ViewModel)等,每个部分都有不同的职责和作用。而在 React 中,它更倾向于将界面拆分成多个可重用的组件,每个组件负责管理自己的状态和 UI,而不是像传统的架构模式那样严格分离模型和视图。

但它仍然可以与这些模式结合使用。例如,可以将 React 组件作为视图层,结合其他库或框架来管理应用程序的模型和控制器逻辑。

Vue.js 更偏向于模型-视图-视图模型(MVVM),但并不是严格遵循,而是借鉴并结合自己的特点。

单/双向数据绑定

单向数据绑定:Model 的更新会触发 View 的更新,View 的更新不会触发 Model 的更新,它们的作用是单向的。

双向数据绑定:Model 的更新会触发 View 的更新,View 的更新也会触发 Model 的更新,它们的作用是相互的

React 是单向数据绑定,当用户访问 View 时,通过触发 Events 进行交互,而在相应 Event Handlers 中,会触发对应的 Actions,而 Actions 通过调用 setState 方法对 View 的 State 进行更新,State 更新后会触发 View 的重新渲染。可以看出,在 React 中,View 层是不能直接修改 State,必须通过相应的 Actions 来进行操作。

Vue 支持单向数据绑定和双向数据绑定

  • 单向数据绑定:使用v-bind属性绑定、v-on事件绑定或插值形式{{data}}。
  • 双向数据绑定:使用v-model指令,用户对View的更改会直接同步到Model。

双向绑定的优缺点:

优点:比较方便简单。

缺点:属于暗箱操作,无法很好的追踪数据变化。

React 和 Vue 都只是单向数据流,虽然 Vue 有双向数据绑定,但是 Vue 父子组件之间数据传递仍然遵循单向数据流。

React特点

React 是一个用于构建用户界面的 JS 库。React 起源于 Facebook 的内部项目,用来架设 Instagram 网站,并于 2013 年 5 月开源。

特点:

  • 遵循组件设计模式
  • 使用虚拟DOM来高效操作DOM
  • 实现了单向响应数据流
  • JSX 是 JavaScript 语法的扩展, 可以直接在 JS 中写 XML 语法。

JSX

JSX即Javascript XML,它是对JS的语法扩展,可以直接在JS中写XML语法,JSX会将类似XML的语法转化为原生的JS。要在JSX中执行JS,需要写在{}中。

为了使浏览器能够读取 JSX,需要用像 Babel 这样的 JSX 转换器将 JSX 文件转换为 JavaScript 对象,然后再将其传给浏览器。

JSX 结构最终会被翻译为 React.createElement 的结构。

组件和不同类型

React 中一切都是组件,我们通常将应用程序的整个逻辑分解为小的单个部分,每个单独的部分称为组件。

组件类型:

按状态分为无状态组件和有状态组件:

无状态组件也被称为"纯函数组件",就是不维护自己的state,只负责接收props渲染DOM。

对于这种无状态的组件,使用函数式的方式声明,会使得代码的可读性更好,并能大大减少代码量。

注:函数组件没有生命周期。(React Hooks 提供了一种在无需编写 class 的情况下使用 state 和其他 React 特性的方式。Hooks 使得在函数组件中引入和复用 state、生命周期方法等)

const Todo = (props) => ( 
    <div onClick={props.onClick}>{props.text}</div> 
)

有状态组件就是组件内部包含状态 state。有状态组件通常会带有生命周期lifecycle,用以在不同的时刻触发状态的更新。

class Hello extends React.Component{
  constructor(props){
    super(props);
    this.state = { 
      tips: "Hello World!"
    }
  }
  componentDidMount() {
    console.log("ComponentDidMount", this);
  }
  render() {
    return (
      <div>{this.state.tips}</div>
    );
  }

应用场景:无状态组件更加简单,适用于展示性组件(比如图片等不需要存数据的),而有状态组件更适合处理复杂逻辑、数据管理和需要内部状态的情况。

按受控可以分为受控组件和非受控组件,主要场景是在表单中:

受控组件:表单元素的值(例如输入框、复选框、下拉框等)由 React 组件的 state 来管理,通过事件处理函数来更新 state,并将 state 的值绑定到表单元素的 value 属性。

import React, { useState } from 'react';

function ControlledComponent() {
  const [inputValue, setInputValue] = useState('');

  const handleChange = (event) => {
    setInputValue(event.target.value);
  };

  return (
    <input
      type="text"
      value={inputValue}
      onChange={handleChange}
    />
  );
}

非受控组件:在非受控组件中,表单元素的值不受 React state 的控制,而是由 DOM 元素自身来管理。通常是通过 ref 来获取表单元素的引用,然后直接在原生 DOM 元素上操作。

function UncontrolledCompenent() {
    const inputRef = useRef();
    
    const handleClick = () => {
        alert(`Input value: ${inputRef.current.value}`);
    }
    
    return (
        <div>
            <input type="text" ref={inpuutRef} />
            <button onClick={handleClick}>Get Input Value</button>
        </div>
    )
}

应用场景:受控组件适用于需要对表单元素进行更细粒度控制、数据验证和处理的场景。非受控组件适用于一些简单的场景,或者需要直接操作 DOM 的情况。可能会减少一些状态管理的复杂性,但也失去了 React 组件对数据流的控制。

Container Components 容器组件和 Components 展示组件/UI组件:

容器组件主要负责数据逻辑和状态管理。包含业务逻辑,例如处理用户输入、发起网络请求等。通常是 class 组件,因为它们需要使用 state 和生命周期方法。

展示组件仅负责 UI 渲染,不处理数据逻辑。接收容器组件传递的数据和回调函数,并将其渲染为用户界面。可以是函数组件或纯函数组件。

通过将容器组件和展示组件分开,我们可以实现代码的分层和逻辑的解耦,使得代码更加清晰和易于维护。

todo

高阶组件(HOC):

高阶组件是将组件作为参数并生成另一个组件的函数。可以提高代码的复用性和灵活性。

高阶组件是装饰器模式在 React 中的实现。

应用例子:

对每个页面做权限控制,若是符合权限则正常渲染页面,不符合则渲染No Role Page. 希望在一个地方统一做权限控制处理

export const withAuth = (WrappedComponent) => {
  const WithAuth = (props) => {
    const { role } = props;
    const currentRole = async () => {
      return await gotRole();
    };
    const [isAdmin, setIsAdmin] = useState(false);
    useEffect(() => {
      if (role === currentRole) {
        setIsAdmin(true);
      }
    }, [role]);
    return isAdmin ? <WrappedComponent {...props} /> : <div>No Role</div>;
  };
  return WithAuth;
};
相关推荐
麒麟而非淇淋33 分钟前
AJAX 入门 day1
前端·javascript·ajax
2401_8581205335 分钟前
深入理解MATLAB中的事件处理机制
前端·javascript·matlab
阿树梢40 分钟前
【Vue】VueRouter路由
前端·javascript·vue.js
随笔写2 小时前
vue使用关于speak-tss插件的详细介绍
前端·javascript·vue.js
史努比.2 小时前
redis群集三种模式:主从复制、哨兵、集群
前端·bootstrap·html
快乐牌刀片882 小时前
web - JavaScript
开发语言·前端·javascript
miao_zz3 小时前
基于HTML5的下拉刷新效果
前端·html·html5
Zd083 小时前
14.其他流(下篇)
java·前端·数据库
藤原拓远3 小时前
JAVAWeb-XML-Tomcat(纯小白下载安装调试教程)-HTTP
前端·firefox
重生之我在20年代敲代码3 小时前
HTML讲解(一)body部分
服务器·前端·html