目标

探讨H5 UI渲染心智模型,即阐述数据是依据什么样的逻辑渲染到界面上的。

本文思路

先通过一个示例讲述不同的数据渲染逻辑,然后讲两个延伸DEMO来着重说明CLASS和FUNCTION的特点;

示例,实现如下一个时钟,页面加载时开始1s跳动一次

实现

一,原生JS直接操作DOM

index.html

<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>React App</title></head><body><!-- 写一个div元素标签用于挂载数据 --><div id="root" /><script type="text/javascript" src="./index.js"></script></body>
</html>

index.js

(() => { // 获取用于挂载数据的元素标签const root = document.getElementById('root')setInterval(() => {// 获取当前系统时间const currentTime = new Date( +new Date() + 8 * 3600 * 1000 ).toJSON().slice(0,19).replace("T"," ")// 将系统时间挂载到元素标签上root.innerText = "当前系统时间是:" + currentTime},1000)
})()

二,通过框架(vue、react、angular等)实现DATA => DOM同步

DATA CHNAGE => 生成新的虚拟DOM,比较与旧DOM 之间的DIFF => DOM CHANGE

1.1,CLASS组件的特点

带有实例this和生命周期(创建,更新,销毁等周期)的组件,组件所有内容(包括数据)都挂在this上,通过this可以获取的组件的最新状态。

1.2,CLASS组件实现时钟
import React from 'react';class ProfilePage extends React.Component {state={time: ''}componentDidMount() {setInterval(() => {// 获取当前系统时间const currentTime = new Date( +new Date() + 8 * 3600 * 1000 ).toJSON().slice(0,19).replace("T"," ")// 将系统时间赋值给statethis.setState({time: currentTime})},1000)}render() {return <div>{this.state.time}</div>;}
}export default ProfilePage;
2.1,FUNCTION组件的特点

没有实例和生命周期的纯函数组件,没有this,数据由hooks维护,可使用Hooks模拟生命周期特性;

什么是 Hooks?

Hooks 是一些可以让你在函数组件里“钩入” React state 及生命周期等特性的函数。

什么是useState?

在这里,useState 就是一个 Hook。通过在函数组件里调用它来给组件添加一些内部 state。

什么是useEffect?

a,你之前可能已经在 React 组件中执行过数据获取、订阅或者手动修改过 DOM。我们统一把这些操作称为“副作用”,或者简称为“作用”。
b,useEffect 就是一个 Effect Hook,给函数组件增加了操作副作用的能力。它跟 class 组件中的 componentDidMount、componentDidUpdate 和 componentWillUnmount 具有相同的触发时机,只不过被合并成了一个 API。
c,当你调用 useEffect 时,就是在告诉 React 在完成对 DOM 的更改后运行你的“副作用”函数。由于副作用函数是在组件内声明的,所以它们可以访问到组件的 props 和 state。默认情况下,React 会在每次渲染后调用副作用函数 —— 包括第一次渲染的时候

// 触发时机等于componentDidMount+componentDidUpdate useEffect(() => {// do some thing})
// 添加依赖后,触发时机等于componentDidMountuseEffect(() => {// do some thing},[])
// 添加return后,,return的触发时机等于componentWillUnmount useEffect(() => {// do some thingreturn () => {// 触发时机等于componentWillUnmount}}, [])
2.2,FUNCTION组件实现时钟
import React, {useState, useEffect} from 'react';function ProfilePage() {const [time, changeTime] = useState('')useEffect(() => {setInterval(() => {// 获取当前系统时间const currentTime = new Date( +new Date() + 8 * 3600 * 1000 ).toJSON().slice(0,19).replace("T"," ")// 将系统时间赋值给statechangeTime(currentTime)},1000)},[])return (<div>{time}</div>);
}export default ProfilePage;

三,延伸DEMO

1,关注demo

点击关注,关注某个人的主页

1.1 公共代码
import React from "react";import ProfilePageFunction from './ProfilePageFunction';
import ProfilePageClass from './ProfilePageClass';class App extends React.Component {state = {user: '凌云',};render() {return (<><label><b>选择你想浏览的主页: </b><selectvalue={this.state.user}onChange={e => this.setState({ user: e.target.value })}><option value="凌云">凌云</option><option value="晓林">晓林</option><option value="江江">江江</option></select></label><h1>欢迎来到 {this.state.user}的 个人主页!</h1><p><ProfilePageFunction user={this.state.user} /><b> (function组件)</b></p><p><ProfilePageClass user={this.state.user} /><b> (class组件)</b></p></>)}
}
export default App;
1.2,CLASSS实现
import React from 'react';class ProfilePage extends React.Component {showMessage = () => {alert('已关注:' + this.props.user);};handleClick = () => {setTimeout(this.showMessage, 3000);};render() {return <button onClick={this.handleClick}>关注</button>;}
}export default ProfilePage;
1.3,FUNCTION实现
import React from 'react';function ProfilePage(props) {const showMessage = () => {alert('已关注: ' + props.user);};const handleClick = () => {setTimeout(showMessage, 3000);};return (<button onClick={handleClick}>关注</button>);
}export default ProfilePage;
1.4,正常情况下没问题,做一个特殊操作

在凌云的主页点击关注,然后在3秒内切换到晓林的主页。
此时,function组件正常;
class组件异常,3秒后,提示关注了晓林。

原因就是上面讲的:

CLASS组件数据挂载在this上,this是在时刻变化的。

处理方式1(其他处理方式不再展开),在发起关注时缓存关注的user
import React from 'react';class ProfilePage extends React.Component {showMessage = (user) => {alert('已关注:' + user);};handleClick = () => {const user = this.props.usersetTimeout(() => {this.showMessage(user)}, 3000);};render() {return <button onClick={this.handleClick}>关注</button>;}
}export default ProfilePage;

2,自增DEMO

实现一个一秒加一的自增计数功能

2.1, 公共代码
import React from "react";import ProfilePageFunction from './ProfilePageFunction';
import ProfilePageClass from './ProfilePageClass';class App extends React.Component {render() {return (<><div><b> (function)</b><ProfilePageFunction /></div><div><b> (class)</b><ProfilePageClass /></div></>)}
}
export default App;
2.2 CLASS实现
import React from 'react';class ProfilePage extends React.Component {state={count: 0}componentDidMount() {setInterval(() => {// 组件挂载时开启定时器,一秒加一this.setState({count: this.state.count + 1})},1000)}render() {return <div>{this.state.count}</div>;}
}export default ProfilePage;
2.3 FUNCTION实现
import React, {useState, useEffect} from 'react';function ProfilePage() {const [count, changeCount] = useState(0)useEffect(() => {setInterval(() => {// 组件挂载时开启定时器,一秒加一changeCount(count + 1)},1000)}, [])return (<div>{count}</div>);
}export default ProfilePage;
2.4,运行后发现

CLASS实现正常,
FUNCTION实现异常:界面从0到1之后,就不走了

原因是:

添加 [ ] 依赖后的useEffect的确在触发时机上和componentDidMount一样,只会在function组件第一次渲染的时候执行一次,后面不再执行,但是它因为没有this,所以这里面拿到的count永远都是初始count=0;

  useEffect(() => {setInterval(() => {// 组件挂载时开启定时器,一秒加一changeCount(count + 1)},1000)}, [])
处理方式1(其他方式不再展开),使用 useRef 来跨越渲染周期存储数据(但是它和 useState 的区别,除了可以跨越渲染周期存储数据,同时对它修改也不会引起组件重新渲染)
import React, {useState, useEffect, useRef } from 'react';function ProfilePage() {const [count, changeCount] = useState(0)const coutRef = useRef(0)const startAdd = () => {setInterval(() => {// 一秒加一coutRef.current = coutRef.current + 1changeCount(coutRef.current)},1000)}useEffect(() => {// 组件挂载时开启定时器startAdd()}, [])return (<div>{count}</div>);
}export default ProfilePage;

参考文档:

1, Dan Abramov博客: 函数式组件与类组件有何不同?
https://overreacted.io/zh-hans/how-are-function-components-different-from-classes/
2,react官方文档:使用Effect Hook
https://react.docschina.org/docs/hooks-effect.html

【问题探讨】H5 UI渲染心智模型相关推荐

  1. DirectX12(D3D12)基础教程(七)——渲染到纹理、正交投影、UI渲染基础

    目录 1.前言 2.渲染到纹理 3.调试支持 4.正交投影 5.UI渲染基础 6.本章完整代码链接 1.前言 记得那是在差不多10多年前,我在工作中认识了一位好兄弟小杨.那时他刚毕业,跟我是同一所大学 ...

  2. React 的心智模型

    本文是 React 核心开发者 Sebastian Markbåge 撰写,阐述了他设计 React 的初衷及与 React 相关的最基础的理论概念.阅读此文,你能站在更高的高度去思考关于 React ...

  3. 2.react心智模型(来来来,让大脑有react思维吧)

    人人都能读懂的react源码解析(大厂高薪必备) 2.react心智模型(来来来,让大脑有react思维吧) 视频课程&调试demos ​ 视频课程的目的是为了快速掌握react源码运行的过程 ...

  4. Web3 网络效应:五种心智模型

    Web3 网络效应:五种心智模型 在过去的十年里,网络效应推动了Web2平台的崛起,也奠定了其主导地位,同时激发了建设者和投资者的想象力.一些人认为网络效应在Web3中会更加强大,而另一些人则认为We ...

  5. 【Unity基础】UI——小地图的制作 UI界面显示人物模型

    小地图的制作 [思路] 小地图的主要思路是用摄像机拍摄以人物为中心的一小步部分区域,把拍摄的图片实时渲染到UI界面的Img图片上. 首先需要一个摄像机 , 用来垂直拍摄人物的头顶,把模式改成正交模式, ...

  6. 心智模型四剑客 之 MEC与攀梯术

    http://piglili.blogbus.com/ 一.攀梯术是什么? 攀梯术是一种一对一深访中使用的探询(probing)技术,用于挖掘人们如何利用某些概念来组织他们关于某事/物的想法,以及这些 ...

  7. OPhone 3D开发之解析渲染MS3D模型

    OPhone 3D开发之解析渲染MS3D模型 OPhone平台中,3D模块已经成为一项标准配置,而且随着硬件成本的降低,搭配硬件加速图形芯片 的移动设备也越来越多地出现在人们的视野当中,手机上的3D再 ...

  8. Unity中如何通过UI显示3D模型解决方案?

    需求:实现将3D模型显示在2DUI上面,实现王者荣耀英雄商城之中英雄展示功能,3D模型可以旋转,添加特效等正常3D功能. 使用RenderTexture和RawImage做相机映射 使用ScreenS ...

  9. 函数式组件与类组件区别-心智模型

    与React类组件相比,React函数式组件究竟有何不同? 区别:心智模型不同,函数式组件捕获了渲染所用的值. 函数式组件与类组件有何不同? - Overreacted他们是完全不同的宝可梦哦.htt ...

最新文章

  1. 我不知道风是在哪一个方向吹
  2. ubuntu 18.10无法locate boot-repair
  3. 纯英文换行的css,利用CSS实现纯英文数字自动换行
  4. 关于QTP 9.2 .NET 插件破解的尝试
  5. 更换mysql-connector-java-6.0.5jar包后程序出现的两个异常及解决方法
  6. CF618F Double Knapsack 构造、抽屉原理
  7. DBI接口和DPI接口的区别
  8. SharePoint Designer 2010中的外部内容类型-SQL Server
  9. mysql碎片data free_浅析MySQL数据碎片的产生(data free)
  10. java实现gps定位_GPS定位数据的提取与存储系统的设计
  11. [架构之路-42]:目标系统 - 系统软件 - Linux下的网络通信-2-无线局域网WIFI原理、WIFI与3G/4G/以太网/蓝牙的协议转换
  12. Mac下Android 反编译
  13. Lumion 9.0 动画渲染的10个技术技巧
  14. Java 接收OutLook 微软邮箱邮件
  15. torch.nn.MSELoss的用法
  16. spring boot整合微信支付
  17. 什么叫死区时间_关于pwm死区时间的介绍
  18. PDPS软件:机器人固定点焊虚拟仿真操作方法
  19. electron-vue通过配置文件设置baseUrl
  20. 数据仓库和数据集市的概念、区别与联系

热门文章

  1. 被组团感谢的百度地图时光机背后,看有爱和情怀产品的修炼法则
  2. 百度竟然放弃浏览器了?
  3. 软件需求——需求基础
  4. Android 打包aar包含第三方aar 实践
  5. 【图像处理】基于形态学的图像处理技术
  6. 西门子串口通讯08-CP341在STEP7环境中做Modbus从站通讯
  7. gith设置本地用户名和邮箱并生成ssh密钥
  8. jsp中C标签c:forEach的使用
  9. c语言中标签的作用域,C语言:goto标签的作用域到底是什么(疑惑)?
  10. 重磅:阿里巴巴将取消“361”制度,不再强制领导给员工绩效评级