大家好,又见面了,我是你们的朋友全栈君。
摘要(本人感受)
此文章是本人在学习React过程中总结起来的一些小经验,因自己在网络上找到的React的教程很多都是一上来就是构建复杂的React环境,Webpack,ES2015等技术的使用,让其简洁的React变得复杂化。本文只为分享简洁的学习过程,让大家理解React,当然其中的不足之处,还望大家指出,谢谢。
React特点
1、虚拟DOM: React也是以数据驱动的,每次数据变化React都会扫码整个虚拟DOM树,自动计算与上次虚拟DOM的差异变化,然后针对需要变化的部分进行实际的浏览器DOM更新。
2、组件化: React可以从功能角度横向划分,将UI分解成不同组件,各组件都独立封装,整个UI是由一个个小组件构成的一个大组件,每个组件只关系自身的逻辑,彼此独立。
3、单项数据流:React设计者认为数据双向绑定虽然便捷,但在复杂场景下副作用也是很明显,所以React更倾向于单向的数据流动-从父节点传递到子节点。
理解了React的特点之后,开始学习React的基本组件。
一、 Hello World开始
刚开始学习React,暂时不考虑工程化的问题,React的运行环境十分简单,只需要在HTML文件中引入2个js(react.js 和 react-dom.js)文件即可开始工作。
react.js:实现React核心逻辑,但是与具体的渲染引擎无关,从而可以跨平台公用。如果需要迁移到React Native,这部分逻辑是不需要改变的。
react-dom.js:包含了具体的DOM渲染更新逻辑,以及服务端渲染的逻辑,这部分就是与浏览器相关了。
作为程序员,学习的第一步就是 Hello World的开始。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="./react.js"></script>
<script src="./react-dom.js"></script>
</head>
<body>
<div id="container"></div>
<script>
//创建Hello组件
var HelloComponent =React.createClass({
render:function(){
return React.createElement('h1',null,'Hello world');
}
});
ReactDOM.render(
React.createElement(HelloComponent,null),
document.getElementById('container')
)
</script>
</body>
</html>
复制代码
在上面这段代码中 React.createClass的作用是注册一个组件类HelloComponent,这个组件类只包含了一个render函数,这个函数通过调用React.createElement实现了以下HTML的内容:
这是React在创建组件时使用的基本语法,在后面我们学习了JSX的语法后,这种写法就不适用了,所以目前先记住这种使用。
二、初识JSX语法
JSX也就是JavaScript XML,它是使用XML标记来创建虚拟DOM和声明组件,在上节介绍中,我们发些在书写方面有些麻烦,影响开发效率问题,比如会出现JavaScript代码与标签混写一起、缺乏一些模板的支持,但是使用JSX,则可以有效的解决这些问题。
加入JSX语法支持
如果我们在代码书写中需要使用JSX的语法,可以使用Babel来进行转换,个人是直接引入Babel的核心文件browser.min.js。如果需要使用,可以去网上提供的静态资源库引用www.bootcdn.cn/ ,可以自行搜索下载哦。
使用JSX语法书写Hello World
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="https://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
var HelloComponent =React.createClass({
render:function(){
return <h1>Hello World</h1>
}
});
ReactDOM.render(
<HelloComponent />,
document.getElementById('container')
)
</script>
</body>
</html>
复制代码
通过这种写法可以发现JSX的好处:
- 可以使用熟悉的语法来仿照HTML来定义虚拟DOM;
- 与JavaScript之间等价转换,程序代码更加直观;
- JSX还可以防注入攻击。React DOM 在渲染之前默认会过滤所有传入的值。它可以确保你的应用不会被注入攻击。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止 XSS(跨站脚本) 攻击。
Vue中可以使用{
{ }}表达式的写法,React中我们只需要一个{ }表达式即可支持。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="https://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
var HelloComponent =React.createClass({
render:function(){
//三元表达式
return <h1>Hello {
true?'World2':''}</h1>
}
});
ReactDOM.render(
<HelloComponent />,
document.getElementById('container')
)
</script>
</body>
</html>
复制代码
需要注意的是表达式中不支持if…else这样的语句,但是支持三元运算符和二元运算符。
三、进阶JSX语法
上一节中了解到基本的JSX语法,这节深入了解一下,这边会给大家提醒一些小坑,帮助大家更好的节约学习时间。
JSX数组遍历 学习过vue的小伙伴们一定知道,在vue中通过v-for的方式去遍历出数组中的内容,而在React中用JSX语法中用表达式的方式去进行数组的遍历。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="https://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
let names = ['React','Vue','Angular'];
var NameComponent = React.createClass({
render:function(){
// 此处有坑哦
return <div>
{
names.map(function(name){
return <div key={name}>Hello,{name}!</div>
})
}
</div>
}
});
ReactDOM.render(
<NameComponent />,
document.getElementById('container')
)
</script>
</body>
</html>
复制代码
在我们注重格式化书写的时候,可能会在render函数中的return后进行断开书写,这样显得格式化更好些:
如果这样书写,你将会看到:
控制台报错了,一脸懵!!!
在React中,render函数中的return后必须接上返回内容,否则会认为无值返回,控制台会报错提示。在其他的return中若没接上返回内容,虽然不会报错,但是会以无值形式返回,导致渲染不出后面的数据。
在此你可以在return后面加上一个(),这样你就可以进行格式化书写了:
我们发现在数组遍历中我们都需要加上遍历的key,无论是vue或者是React中都需要使用key,如果没有key虽然会出来效果,但是控制台会报错。key的作用是生成虚拟DOM时,需要使用key来进行标记,DOM更新时进行比较。
{
names.map(function(name){
return <div key={name}>Hello,{name}!</div>
})
}
复制代码
如果无key的添加:
数组中的JSX
JSX允许在模板中插入JavaScript变量,如果这个变量是一个数组,就会展开这个数组的所有成员。
let arr=[
<h1 key="1">我是React!</h1>,
<h2 key="2">我是Vue!</h2>
];
ReactDOM.render(
<div>{arr}</div>,
document.getElementById('container')
)
复制代码
四、Props和State的学习
React组件可以把它看作带有props属性集合和state状态集合并且构造出一个虚拟DOM结构的对象。
Props
props是组件中固有属性的集合,其数据由外部传入,一般在整个组件的生命周期中都是只读的。属性的初始值通常由React.createElement函数或者JSX中标签的属性值进行传递,并合并到组件实例对象的this.props中。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Props</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="https://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
<style>
</style>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
let HelloBox = React.createClass({
render:function(){
return (<div>{
'Hello '+this.props.name}</div>)
}
})
ReactDOM.render(
<HelloBox name='React' />,
document.getElementById('container')
)
</script>
</body>
</html>
复制代码
this.props后面携带的值需要与组件传递的属性值保持一致。
State
组件总是需要和用户互动的。React的一大创新,就是将界面组件看成一个状态机,用户界面拥有不同状态并根据状态进行渲染输出,用户界面和数据始终保持一致。开发者的主要工作就是定义state,并根据不同的state渲染对应的用户界面。
举个实例让大家感受一下:
这个例子包含一个input框和一个button,通过点击button来改变input的disable状态。
复制代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Props和State</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="https://cdn.bootcss.com/babel-core/5.8.38/browser.mim.js"></script>
<style>
input:disabled{
border: 1px solid red;
}
button{
cursor: pointer
}
</style>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
var TextBoxComponent = React.createClass({
//初始化原始数据 ,与Vue中的data类似
getInitialState:function(){
return {
enable:true
}
},
render:function(){
return(
<p>
//通过this.state去获取enable的初始化值
<input type="text" disabled={this.state.enable} />
<button>改变状态</button>
</p>
)
}
})
ReactDOM.render(
<TextBoxComponent />,
document.getElementById('container')
)
</script>
</body>
</html>
复制代码
目前暂时还不能点击button去改变disable的状态,在React单向数据流的条件下,我们无法向Vue那样直接去操作改变disable的状态,需要去借助setState函数去处理。
setState函数
通知React组件数据发生变化的方法是调用成员函数setState(data,callback)。这个函数会合并data到this.state,并重新渲染组件。渲染完成后,调用可选的callback回调。(大部分情况下不需要调用回调,因为React会负责把界面更新到最新状态)
因此我们给button加上我们的点击事件,通过setState去改变disable的值。
在上面的代码中我们需要注意几点:
- getInitialState函数必须有返回值,可以是null,false,一个对象。
- 访问state数据的方法是”this.state.属性名”。
- 变量用{ }包裹,不需要再加双引号。
props与state的区别
props不能被其所在的组件修改,从父组件传递进来的属性不会在组件内部更改;
state只能在所在组件内部更改,或在外部调用setState函数对状态进行间接修改。
五、React生命周期
一个组件完整的生命周期包含实例化阶段、活动阶段、销毁阶段三个阶段。每个阶段又由相应的方法管理。
这些过程中涉及三个主要的动作术语:
mounting: 表示正在挂载虚拟DOM到真实DOM;
updating: 表示正在被重新渲染;
unmounting:表示正在将虚拟DOM移除真实DOM。
在每个动作术语中提供了一些函数供我们使用:
componentWillMount():表示将要或正挂载过程中;
componentDidMount():表示已经挂载完成了;
componentWillUpdate(object nextProps, object nextState):表示将要或正在重新渲染;
componentDidUpdate(object prevProps, object prevState):表示重新渲染完成了;
componentWillUnmount():表示虚拟DOM卸载了。
通过一个简单的实例,来看React组件的生命周期。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>生命周期</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="https://cdn.bootcss.com/babel-core/5.8.38/browser.min.js"></script>
<style>
</style>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
var AddCount = React.createClass({
//数据初始化
getInitialState:function() {
console.log('1-getInitialState')
return {
count:1
}
},
componentWillMount() {
console.log('2-componentWillMount')
},
componentDidMount(){
console.log('3-componentDidMount')
},
componentWillUpdate(){
console.log('4-componentWillUpddate')
},
componentDidUpdate(){
console.log('5-componentDidUpdate')
},
handleClick:function(event){
this.setState({
count:this.state.count+1
})
},
render:function(){
return(
<p>
{this.state.count} <br/>
<button onClick={this.handleClick}>点击加一</button>
</p>
)
}
})
ReactDOM.render(
<AddCount />,
document.getElementById('container')
)
</script>
</body>
</html>
复制代码
点击之后:
六、获取真实DOM节点
React中的DOM也是虚拟DOM(virtual DOM),这点跟Vue非常类似。只有当它插入文档以后,才会变成真实的DOM。React也是在虚拟DOM发生变化时,进行比对后,只渲染变化的部分,它是React极高性能的主要原因之一。
但是有时候我们需要从组件中获取真实的DOM节点,来进行业务逻辑的编写,React为我们提供了ref属性。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>ref</title>
<script src="./common/react.js"></script>
<script src="./common/react-dom.js"></script>
<script src="https://cdn.bootcss.com/babel-core/5.8.38/browser.mim.js"></script>
<style>
</style>
</head>
<body>
<div id="container"></div>
<script type="text/babel">
var MyComponent = React.createClass({
handleClick:function(event){
//通过this.refs去获取,这点和Vue相似
this.refs.myTitleInput.focus();
},
render:function() {
return(
<div>
<input type="text" ref="myTitleInput" /> <br/>
<input type="button" value="Focus on input" onClick={this.handleClick} />
</div>
)
}
})
ReactDOM.render(
<MyComponent/>,
document.getElementById('container')
)
</script>
</body>
</html>
复制代码
通过这些知识点的学习,可以初步的了解到React的基本知识。下一章将分享React的表单应用。如果有不对的地方还希望大家留言指出,谢谢!
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/107016.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...