React简介、虚拟DOM、Diff算法、创建React项目、JSX语法、组件、组件声明方式、组件传值props和state、组件的生命周期

React简介:

前面只是简单介绍移动APP开发,后面还会继续深入介绍移动app开发;其中想要用ReactNative开发出更出色的应用,那么就得学好React,下面将介绍React:

React 是一个由 Facebook 开发用于构建用户界面的渐进式 JavaScript 库,其特点:声明式设计、高效、灵活、JSX、组件化、单向数据流。

React也是组件化的,与vue不同的是:React直接使用JS代码编写组件(结构、样式、逻辑混合在js代码中)。

React是前端三大框架中诞生最早的框架,社区庞大,技术团队实力雄厚。

虚拟DOM:

操作原生DOM是一件非常耗性能的事,操作虚拟DOM就不会那么耗性能了,操作虚拟DOM时采用Different算法,只更新变化的虚拟DOM部分;虚拟DOM指通过程序员手动模拟出来类似原生DOM的对象,如下面模拟一个带有链接的p元素:

	var p = {//定义一个对象tagName:'p',//标签名为:pattrs:{//定义属性:class:'font16'},children:[//定义内容,相当于innerText'跳转到:',{//在父标签的children中再定义以对象,其方法和定义p一样:tagName:'a',//标签名为:aattrs:{//属性:href:'https://www.baidu.com',},children:[//定义内容:'百度']}]}

Diff算法:

Diff算法用于对比新旧虚拟DOM的算法,其中有三部分:tree diff、component diff、element diff,其区别:

tree diff :新旧DOM树逐层对比的方式,对比所有层节点来找到被更新的节点后修改旧DOM。

component diff:组件之间的对比,当对比组件的时候,如果两个组件的类型相同,则这个组件暂时不需要被更新,如果组件的类型不同,则立即移除旧组件,新建一个组件,替换到被移除的位置。

element diff:组件中每个元素之间的对比。

使用虚拟DOM创建React项目(导入资源型):

使用React开发项目时,必须安装两个包:react、react-dom;react是用来创建组件、组件生命周期等。react-dom用来操作DOM。创建react项目步骤:

	//1.新建一个项目文件夹,并在文件夹打开终端键入:npm init -y 初始化一个package.json文件//2.终端输入:cnpm install react react-dom --save 安装react和react-dom到运行里,ReactNative开发中不建议使用cnpm装包//3.新建src文件夹并新建main.js文件并引入:react和react-dom:开始编写react中js主文件(并新建index.html文件,文件中留渲染的div)import React from 'react';import ReactDOM from 'react-dom';//4.在main.js文件中使用React提供的API操作元素://4-1使用React.createElement()创建一个虚拟DOM,接收至少三个参数:参数1:字符串(标签类型),参数2:对象(标签属性),参数3开始:当前元素子节点,可放多个虚拟dom,如:var mydiv = React.createElement('div',{class:'mydiv',id:'box'},'这是一个div元素');//<div class='mydiv' id='box'>这是一个div元素</div>var spanp = React.createElement('span',{class:'spans'},'被span标签包裹的文本');//<span class='spans'>被span标签包裹的文本</span>var textp = React.createElement('p',{class:'tp'},'p标签文本中',spanp);//<p class='tp'>p标签文本中<span class='spans'>被span标签包裹的文本</span></p>// 4-2使用ReactDOM.render()将虚拟DOM渲染到页面中,参数1:渲染DOM内容,参数2:渲染的dom元素位置(获取DOM的方式),如:ReactDOM.render(mydiv,document.getElementById('app'));//这里app表示index.htlm文件中一个id值为app的标签,如<div id='app'></div>//4.webpack打包构建后,在dist目录下的文件是正常可以访问的。

JSX:

不难发现使用js创建元素的方式是非常繁琐的,因此这里介绍一款可以解决这个问题语法:JSX;

HTML 语言直接写在 JavaScript 语言中,不加任何引号,这就是 JSX 语法,它允许 HTML 与 JavaScript 的混写;

它是 一种 JavaScript 的语法扩展, 我们推荐在 React 中使用 JSX 来描述用户界面,JSX 是在 JavaScript 内部实现的;元素是构成 React 应用的最小单位,JSX 就是用来声明 React 当中的元素(底层实际就是通过上面js创建元素的)使用JSX语法时首先要安装:(cnpm install babel-preset-react -D)并配置在.babelrc文件中,babel-preset-react 用来转换JSX代码。(注意新版本:babel-preset-react-app,此环境应该基于上面环境)

与浏览器的 DOM 元素不同,React 当中的元素事实上是普通的对象,如:

	// 注意:想要正常运行JSX语法:还需要以下两步://1.在项目目录下新建:.babelic文件,其配置代码如下:{"presets": ["env", "stage-0", "react"],"plugins": ["transform-runtime"]}//2.cnpm i babel-preset-env babel-preset-stage-0 babel-plugin-transform-runtime --save ,下载上面配置依赖的包。//3.配置完以上环境后,应该使用webpack打包后才可以以files的方式打正常访问react项目import React from 'react';import ReactDOM from 'react-dom';var titles = '这是一个提示';var elements =<div>{/* JSX语法中允许有一个根节点,根节点中可以嵌套其它元素 */}<p title={titles}>hello</p>{/*JSX中使用变量用{}包裹,实际指使用js语法时用{}包裹*/}<a href="#">hello</a><p className='textp'>hello</p>{/*在JSX中使用className代替class属性,因为class在js中只一个关键字*/}<label htmlFor="">hello</label>{/* 在JSX中for使用htmlFor代替 */}</div>const box = document.getElementById('box');ReactDOM.render(elements,box);//总结://1.当编译时遇到尖括号<>当JSX执行,当遇到大括号{}当js执行//2.JSX语法中使用className代替class属性//3.在JSX中for使用htmlFor代替//4.jsx语法中只能使用一个根元素//5.jsx中数组会自动展开

JSX 中注释:

写法一:

	{// 注释// ...}

写法二(单行推荐):

	{/* 单行注释 */}

写法三(多行推荐):

	 {/** 多行注释*/}

JSX 不同写法:

Babel 会把 JSX 通过React.createElement() 函数编译,每个 React 元素都是一个真实的 JavaScript 对象;下面几种方式是等价的,如:

	const element = (<h1 className="greeting">Hello, world!</h1>);const element = React.createElement('h1',{className: 'greeting'},'Hello, world!');const element = {type: 'h1',props: {className: 'greeting',children: 'Hello, world'}};const element = {tagName:'h1',attrs:{className: 'greeting'},children:['Hello, world']}

组件:

React 允许将代码封装成组件,然后像插入普通 HTML 标签一样,在网页中插入这个组件即可使用;组件规则注意事项:组件名的第一个首字母必须大写,class声明式组件必须有 render 方法,组件内必须有且只有一个根节点,组件的属性可以在组件内通过props 获取(函数需要传递参数:props;类直接通过: this.props),如:

函数式声明组件(无状态):

名字不能用小写,React 在解析的时候,是以标签的首字母来区分的,如果首字母是小写则当作 HTML 来解析,如果首字母是大写则当作组件来解析。

	 // 函数名大写,组件名为函数名// 函数式声明组件,必须有return关键字,即使没内容也应该:return nullfunction Header(props){return (//当返回多行代码时,建议使用小括号括起来<div><p>这是header组件{props.name}</p>{/* 这里直接通过{属性名}的方式是不能拿到属性值的,需要给函数传递一个参数如:props等,在通过这个参数点出属性:{props.name},且这些属性只读 */}</div>)}const box = document.getElementById('box');// 通过 <函数名/> 的方式定义组件名;组件中传递参数使用属性的方式,如:name={变量名},age={变量名};分开传递参数很不方便,可以使用es6中属性扩散语法传递一个对象达到同样效果:var obj = {name:'jack',age:'28',gender:'男'}var cont = <div><Header {...obj}/> {/* es6中属性扩散语法 */}</div>ReactDOM.render(cont,box);

抽离组件:

上面组件声明在同一个js文件中,没有达到减少主文件代码量的问题,想要减少主文件代码量,就得将组件抽离出来,如:

	 // 被抽离的组件header.js文件:(扩展:组件可以使用jsx后缀名,但是需要在webpack.config.js文件中配置解析jsx文件的loader:loader和js一样,可连写为:( js|jsx)$ 、jsx?$ )import React from 'react';//导入React,注意:React首字母必须大写function Header(props){return (<div><p>这是header组件{props.name}</p></div>)}// 抽离组件需要暴露出:export default Header;//或直接在函数或类前面加 export default;// 在主文件(main.js)中使用这个组件:// 导入组件:import Header from './components/header.js';// 在主文件中使用 <Header><Header/> (简写:<Header/>)使用组件即可

类方式声明组件(有状态):

	// 通过class定义一个Header组件,extends 继承了React中Componentclass Header extends React.Component { render() { //使用render函数,函数中返回组件类容:return (<div><p>这是header组件{this.props.names}</p>{/*class声明的组件拿传递的值通过:this.props点属性名,也是只可读的*/}</div>)}}; ReactDOM.render(<Header names='jack'/>, document.getElementById('box'));// 抽离组件的方式和函数声明组件的方式中一样

组件传值props和state:

state 和 props区别在于props 是不可变的,而 state 可以改变。函数式组件只能通过 props 来传递数据,不能通过state传值;class定义的组件都可以使用它们传值。

	class Header extends React.Component { constructor(props){//class定义的类中如果实现了继承,默认就有constructor函数,只是看不见;当写出这个构造函数时,要通过super调用:super(props);//表示父类的构造函数console.log(props);//在constructor中是不能直接使用props的,想要使用,就得在constructor中传递props// constructor中的this.state表示私有数据对象,类似vue中data(){},this.state中定义的数据是可改变的,通过this.state点属性拿到,如:this.state={messages:'hello',names:'jack'}}render() { return (<div><p>这是header组件{this.props}</p><p>这是header组件{this.state.messages}</p><button onClick={this.change}>变更messages的值</button>{/* jsx中使用事件时,必须使用驼峰命名法,且处理函数名前面加this. */}</div>)}//React函数中this默认指向undefined,若想this指向class类,可以使用箭头函数:如:// change(){//   this.state.messages = '修改hello为word';// }change=()=>{//这里是将箭头函数赋值给change,箭头函数中this依旧指向class类// this.state.messages = '修改hello为word';//通过this.state方式修改数据只是单向的,内存中数据是修改了,但是页面没有自动刷新,因此也不推荐,推荐setState()方法异步修改,如// this.setState({//setState()方法中传递一个对象,对象中传入要修改的属性,如://   messages:'word',//   names:'lucky'// })// this.setState(function(prevState,props){//setState也支持传递一个函数,但是函数必须return一个对象;函数中第一个参数表示修改数据之前的数据,第二个参数是外界传递过来的数据属性//   return {//     messages:'word'//   }// })this.setState(function(prevState,props){//setState()因为setState是异步修改数据的,想要确保拿到最新的数据,那么,可以给setState继续传递一个参数为:回调函数,在回调函数里面拿到的数据是比较保险的,如:return {messages:'word'}},function(){console.log(this.state.messages);})}}; ReactDOM.render(<Header/>, document.getElementById('box'));// 抽离组件的方式和函数声明组件的方式中一样

组件的生命周期:

组件从创建到运行再到销毁,这期间伴随着各种各样的事件,这些事件统称为组件的生命周期函数;

组件生命周期分为三部分:组件创建阶段(命周期函数一生只创建一次)、组件运行阶段(生命周期函数根据props和state的状态是否改变运行0-N次)、组件销毁阶段(生命周期函数一生只执行一次)。

	import React from 'react';import ReactDOM from 'react-dom';import ReactTypes from 'prop-types';//导入数据校验模块class Header extends React.Component { constructor(props){super(props);//1.使用:this.state={}初始化组件私有状态,初始化组件私有数据this.state={messages:'hello',numstate:props.num//因为props中的值时只读的,想要修改值,就得使用state存值,但是state存的值是固定的,因此这里可以传递一个动态的值,即props的值,此时页面的值应该为对应的state值。}}//2.使用:static defaultProps = {}定义默认的值供程序正常运行,如:static defaultProps = {num:0}//3.使用:static propTypes = {}做数据校验,防止传过来的数据无效,如:static propTypes = {//特别注意:做校验需要安装一个包prop-types: npm install prop-types ,并在开头导入num:ReactTypes.number//如果需要检验其他数据类型,可阅读prop-types原文;当做完数据校验时,在组件中传递过来的值类型不符合时会报警告}// 4.使用:componentWillMount(){}组件即将被挂载到页面时触发函数,虚拟DOM也没创建(不能被拿到),因此此页面不能操作页面,可以操作数据,如:componentWillMount(){console.log(this.state.messages);//数据可被拿到console.log(this.props.num);//数据可被拿到this.myFunction();//函数可被调用console.log(document.getElementById('testp'));//不能被获取}// 5.使用:render(){}即将渲染内存中的虚拟DOM,该函数执行完后内存中已经渲染好数据了,但是还没有被挂载到页面上,如:render() { //render中不能使用this.setState方法,否则会进入死循环return (<div>{/* <p id='testp'>num的值:{this.props.num}</p> */}<p id='testp' onClick={this.addnumstate}>num的值自增为:{this.state.numstate}</p>{/*修改为可改变的state值*/}<span ref='spans'>hello</span>{/* 利用refs属性可以快速获取到该节点 */}</div>)}// 6.使用:componentDidMount(){}页面已经有可见的DOM元素了,此时可以拿到render中的DOM,如:componentDidMount(){console.log(document.getElementById('testp'));//可以获取DOM元素,可对其进行操作(原生DOM型,但是需要注意this指向问题,可使用箭头函数,但是不推荐原生方式),如:// document.getElementById('testp').οnclick=()=>{//   this.setState({//     numstate:this.state.numstate++//   })// }//推荐React中事件绑定的方式,如testp标签中}//7.使用:conmponentWillReceiveProps(){}当子组件的属性props改变时触发此方法,但是第一次渲染时不会被触发,如:conmponentWillReceiveProps(nextProps){//这里的数据是旧的,但是通过第一个参数nextProps.属性名,拿到的是最新的数据console.log('当外界传递过来新的props时,才会触发该事件执行');console.log(next.Props.num);}addnumstate=()=>{//使用箭头函数改变this指向为类的实例;注意:在dom中掉用次函数时在函数名前加thisthis.setState({numstate:this.state.numstate++})}myFunction(){console.log('测试componentWillMount是否可以调用外部函数');}// 以上是组件创建阶段生命周期,下面将介绍组件运行阶段生命周期:// 1.使用:shouldComponentUpdate(){}里面return一个布尔值,判断是否要更新页面上数据,当为true时可以改变页面上数据,当为false时不能改变页面上的数据;无论是true或false,内存中数据都是改变重新渲染了shouldComponentUpdate(nextProps,nextState){//此方法中可传入两个参数:第一个表示最新的props,第二个表示最新的stateconsole.log(nextState.numstate);return true;//这里应该使用传入参数做出逻辑后return 布尔值}// 2.当shouldComponentUpdate中返回false时,会重新返回到shouldComponentUpdate执行,若果返回的是true,则执行下面的:componentWillUpdate(){}将要更新数据,此时页面和内存中数据都未被更新,如:componentWillUpdate(){//此时页面上数据都是旧的console.log(this.refs.spans.innerHTML);//使用refs获取ref设置的值}// 3.这里有一个运行时的render方法,但是里面数据h还是旧的。// 4.使用:componentDidUpdate(){}更新了页面和内存中的数据,此时数据都是最新的,如:componentDidUpdate(){//此时页面上数据都是新的console.log(this.refs.spans.innerHTML);}}; ReactDOM.render(<Header num='校验时传入无效数据时,会报警告'/>, document.getElementById('box'));

对上面组件生命周期流程总结如下图:

在这里插入图片描述

提示:本文图片等素材来源于网络,若有侵权,请发邮件至邮箱:810665436@qq.com联系笔者删除。
笔者:苦海

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

去掉 edittext 长按全选_开封消毒湿巾全选

开封消毒湿巾全选   其实&#xff0c;带有杀菌效果的清洁产品大多通过降低微生物的繁殖力达到预期的杀菌效果&#xff0c;所添加的每种杀菌成分都针对特定细菌&#xff0c;无法杀灭所有细菌。如果产品中的杀菌剂浓度总是不能将细菌完全杀灭&#xff0c;就可能导致细菌对该类杀…

代数余子式之和怎么算_小明说养老 | 养老金怎么算之月平均缴费指数怎么来的?...

上一期小明分享了企业职工养老保险退休待遇怎么算&#xff0c;具体可戳小明说养老|养老金怎么算&#xff1f;小明来教你。在以张阿姨为例的计算举例中&#xff0c;提到张阿姨15年的平均缴费指数为0.8209。对这个平均缴费指数的概念提问较多&#xff0c;今天就来解释一下月平均缴…

ReactNative简介、开发环境、调试、常用组件、useState状态、FlatList组件、SectionList组件、Platform 模块、定义样式、图片组件、触摸事件、打包apk发布版

ReactNative简介&#xff1a; ReactNative是基于React语法来进行开发移动app的框架&#xff1b; ReactNative中提供了移动端专用的一些组件&#xff0c;我们要使用ReactNative固有的组件代替网页中使用的一些元素&#xff0c;如&#xff1a;div, p, img 都不能用了&#xff1…

odis工程师使用方法_傅里叶红外光谱仪常见故障维修及排除方法,你了解有多少种呢?...

傅里叶红外光谱仪在使用过程中难免会出现故障&#xff0c;那我们该怎么检修呢&#xff1f;赛默飞傅里叶红外光谱仪有些光谱仪器的使用说明书会给出光谱仪的常见故障及排查方法&#xff0c;有些光谱仪器还有自诊断功能&#xff0c;当傅里叶红外光谱仪不能正常工作时&#xff0c;…

微信小程序简介、发展史、小程序的优点、申请账号、开发工具、初识wxml文件和wxss文件

微信小程序介绍&#xff1a; 小程序简介&#xff1a; 小程序是一种连接用户与服务的方式&#xff0c;它能在微信内被便捷地获取和传播&#xff0c;具有出色的使用体验。 不需要下载安装&#xff0c;用户通过搜一搜或扫一扫就可以打开使用&#xff0c;使用完后退出即可。 小…

tia v15 添加项目_硬技能,TIA 博途软件界面的介绍

在前面的文章中给大家介绍了TIA 博途软件的安装包等介绍&#xff0c;这次小编给大家介绍一下TIA 博途软件的界面。#电工学习PLC#你知道吗&#xff0c;在博途软件的自动化项目任务的创建中&#xff0c;我们可以使用portal视图和项目视图。Portal视图是面向任务的视图&#xff0c…

UIImagePickerController按钮的中文问题

UIImagePickerController按钮的中文问题 执行以下两步即可 1. 在targets中设置region为China 2. 在project中添加支持中文 转载于:https://www.cnblogs.com/YouXianMing/p/3935460.html

rsatool使用步骤图解_工作中想要事半功倍?图解来助你

一次会议上&#xff0c;老板让我们进行一场头脑风暴&#xff0c;然后将脑中浮现出来的想法以ppt的形式&#xff0c;在会议上与大家分享。在会上我看到其他区域的同事做的ppt&#xff0c;真的叫一个精美啊&#xff0c;有图形对比、有案例分析、有未来展望。反观自己的&#xff0…

ZRender源码分析2:Storage(Model层)

回顾 上一篇请移步&#xff1a;zrender源码分析1&#xff1a;总体结构 本篇进行ZRender的MVC结构中的M进行分析 总体理解 上篇说到&#xff0c;Storage负责MVC层中的Model&#xff0c;也就是模型&#xff0c;对于zrender来说&#xff0c;这个model就是shape对象&#xff0c;在…

java语言概述、java语言特性、java语言发展史、java语言作用

Java介绍&#xff1a; Java语言概述&#xff1a; Java语言是由美国Sun&#xff08;Stanford University Network&#xff09;斯坦福网络公司的java语言之父–詹姆斯高斯林&#xff0c;在1995年推出的高级的编程语言。所谓编程语言&#xff0c;是计算机的语言&#xff0c;人们…

电脑显示器不亮主机正常_电脑主机已开机 显示屏却不亮(看完秒懂)

台式电脑是工作的得力助手&#xff0c;我们用的是软件&#xff0c;但是如果硬件出问题了&#xff0c;就无法工作了。有时会遇到台式电脑开机&#xff0c;主机开了&#xff0c;但是屏幕却不亮&#xff0c;是怎么回事呢&#xff1f;现在&#xff0c;笔者告诉大家怎样一步步查明原…

二进制的认识、进制之间的转换、计算机储存单位

二进制&#xff1a; 计算机中的数据不同于人们生活中的数据&#xff0c;人们生活采用十进制数&#xff0c;而计算机中全部采用二进制数表示&#xff0c;它只包含0、1两个数&#xff0c;逢二进一&#xff0c;如&#xff1a;1110。每一个0或者每一个1&#xff0c;叫做一个bit&am…

.net一个函数要用另一个函数的值_VLOOKUP函数

两个表格顺序不同&#xff0c;如何匹配合并&#xff1f;如下图&#xff1a;常常遇到有人问我&#xff0c;两个表格需要按照人名合并起来&#xff0c;但是两表的人名顺序并不相同&#xff0c;怎么处理呢&#xff1f;这个就要用到EXCEL大名鼎鼎的VLOOKUP函数了。具体语法如下&…

外部函数获取内部函数变量_一维随机变量的分布函数

一、分布函数、概率密度(一)一维随机变量的分布函数(二)一维离散型随机变量的概率分布(三)一维连续型随机变量的概率密度(四)一维连续型随机变量的函数的概率密度如&#xff1a;设X的概率密度为f(x), g(x)为连续函数&#xff0c;求Yg(x)的概率密度。方法一、定义法step 1. 求出…

DOS命令、Java语言开发环境(JVM、JDK、JRE)

DOS命令&#xff1a; DOS是一个早期的操作系统&#xff08;黑窗口&#xff09;&#xff0c;现在已经被Windows系统&#xff08;图形化&#xff09;取代&#xff0c;对于我们开发人员&#xff0c;目前需要在DOS中完成一些事情&#xff0c;Java语言的初学者&#xff0c;学习一些D…

shell执行docker命令卡挂住_Docker官方文档翻译4

第四篇&#xff1a;Swarms准备工作安装Docker版本1.13或更高版本。安装Docker compose。安装docker machine阅读第1 2 3部分的内容。确保你已发布并推送到注册仓库的friendlyhello镜像。确保你的镜像可以部署为一个容器。 运行这个命令&#xff0c;在你的信息中插入用户名&…

编写第一个Java程序:helloworld

配置好java开发环境后&#xff0c;我们可以编写第一个java程序&#xff08;helloworld&#xff09;。 在开始编写java程序时&#xff0c;我们要知道java程序开发的三个步骤&#xff1a;编写、编译、运行。 编写阶段主要是由程序员编写后缀为.java的文件&#xff1b;将后缀为.ja…

java中关键字、标识符、常量、变量、数据类型

关键字&#xff1a; JAVA语言中已经定义好的具有特殊含义的单词&#xff0c;被称为关键字&#xff0c;关键字是全小写无特殊字符的纯 英文字母&#xff0c;在编辑器中一般有高亮效果&#xff0c;如public、class、static等。 标识符&#xff1a; 在JAVA语言中&#xff0c;自…

js滚动条下拉一定值_JS逆向 | 无限Debugger之淘大象

置顶公众号今天继续和大家研究JS逆向&#xff0c;不少小伙伴在JS逆向的时候遇到过无限debugger的反爬&#xff0c;今天就拿一个网站练练手感受下无限debugger。分析请求先打开这次的目标网站--淘大象(https://taodaxiang.com/credit2)打开「开发者工具」就自动进入debug&#x…

java中数据类型转换、ASCII编码

数据类型转换&#xff1a; JAVA语言中要求参与计算的数据类型要保持一致&#xff0c;如果不一致则会发生数据类型转换&#xff0c;数据类型转换可分为&#xff1a;自动类型转换&#xff08;隐式转换&#xff09;和强制类型转换&#xff08;显式转换&#xff09;。 自动类型转…