【问题探讨】H5 UI渲染心智模型

2024-04-16 20:08

本文主要是介绍【问题探讨】H5 UI渲染心智模型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目标

探讨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渲染心智模型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/909778

相关文章

QT6中绘制UI的两种方法详解与示例代码

《QT6中绘制UI的两种方法详解与示例代码》Qt6提供了两种主要的UI绘制技术:​​QML(QtMeta-ObjectLanguage)​​和​​C++Widgets​​,这两种技术各有优势,适用于不... 目录一、QML 技术详解1.1 QML 简介1.2 QML 的核心概念1.3 QML 示例:简单按钮

使用雪花算法产生id导致前端精度缺失问题解决方案

《使用雪花算法产生id导致前端精度缺失问题解决方案》雪花算法由Twitter提出,设计目的是生成唯一的、递增的ID,下面:本文主要介绍使用雪花算法产生id导致前端精度缺失问题的解决方案,文中通过代... 目录一、问题根源二、解决方案1. 全局配置Jackson序列化规则2. 实体类必须使用Long封装类3.

Idea插件MybatisX失效的问题解决

《Idea插件MybatisX失效的问题解决》:本文主要介绍Idea插件MybatisX失效的问题解决,详细的介绍了4种问题的解决方法,具有一定的参考价值,感兴趣的可以了解一下... 目录一、重启idea或者卸载重装MyBATis插件(无需多言)二、检查.XML文件与.Java(该文件后缀Idea可能会隐藏

Python Selenium动态渲染页面和抓取的使用指南

《PythonSelenium动态渲染页面和抓取的使用指南》在Web数据采集领域,动态渲染页面已成为现代网站的主流形式,本文将从技术原理,环境配置,核心功能系统讲解Selenium在Python动态... 目录一、Selenium技术架构解析二、环境搭建与基础配置1. 组件安装2. 驱动配置3. 基础操作模

在 PyQt 加载 UI 三种常见方法

《在PyQt加载UI三种常见方法》在PyQt中,加载UI文件通常指的是使用QtDesigner设计的.ui文件,并将其转换为Python代码,以便在PyQt应用程序中使用,这篇文章给大家介绍在... 目录方法一:使用 uic 模块动态加载 (不推荐用于大型项目)方法二:将 UI 文件编译为 python 模

Nginx 访问 /root/下 403 Forbidden问题解决

《Nginx访问/root/下403Forbidden问题解决》在使用Nginx作为Web服务器时,可能会遇到403Forbidden错误,文中通过示例代码介绍的非常详细,对大家的学习或者工作... 目录解决 Nginx 访问 /root/test/1.html 403 Forbidden 问题问题复现Ng

Python的pip在命令行无法使用问题的解决方法

《Python的pip在命令行无法使用问题的解决方法》PIP是通用的Python包管理工具,提供了对Python包的查找、下载、安装、卸载、更新等功能,安装诸如Pygame、Pymysql等Pyt... 目录前言一. pip是什么?二. 为什么无法使用?1. 当我们在命令行输入指令并回车时,一般主要是出现以

Nginx部署React项目时重定向循环问题的解决方案

《Nginx部署React项目时重定向循环问题的解决方案》Nginx在处理React项目请求时出现重定向循环,通常是由于`try_files`配置错误或`root`路径配置不当导致的,本文给大家详细介... 目录问题原因1. try_files 配置错误2. root 路径错误解决方法1. 检查 try_f

Python解决雅努斯问题实例方案详解

《Python解决雅努斯问题实例方案详解》:本文主要介绍Python解决雅努斯问题实例方案,雅努斯问题是指AI生成的3D对象在不同视角下出现不一致性的问题,即从不同角度看物体时,物体的形状会出现不... 目录一、雅努斯简介二、雅努斯问题三、示例代码四、解决方案五、完整解决方案一、雅努斯简介雅努斯(Janu

MySQL索引失效问题及解决方案

《MySQL索引失效问题及解决方案》:本文主要介绍MySQL索引失效问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录mysql索引失效一、概要二、常见的导致MpythonySQL索引失效的原因三、如何诊断MySQL索引失效四、如何解决MySQL索引失