ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

React 入门

2021-06-21 18:29:40  阅读:220  来源: 互联网

标签:入门 render React PropTypes props 组件 ReactDOM


React 背景知识

React 是一个用于构建用户界面的 JavaScript 库,主要用于构建 UI,而不是一个 MVC 框架,但可以使用 React 作为 MVC 架构的 View 层轻易的在已有项目中使用,它是一个用于构建用户界面的 JavaScript 库,起源于 Facebook 的内部项目,用来架设 Instagram 的网站,于 2013 年 5 月开源。

React 特点

  • 1.声明式设计 −React采用声明范式,可以轻松描述应用。

  • 2.高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。

  • 3.灵活 −React可以与已知的库或框架很好地配合。

  • 4.JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。

  • 5.组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。

  • 6.单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。

环境准备

方式一:在浏览器中编写代码

  • 直接在浏览器选项卡中使用codepen编写

方法二:直接使用 Staticfile CDNReact CDN

  • 直接使用 Staticfile CDN 的 React CDN 库,地址如下:
<script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
  • 官方提供的 CDN 地址:
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<!-- 生产环境中不建议使用 -->
<script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script>
  • 使用实例如下,直接打开index.html页面会输出 Hello, world!:
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>
<body>

<div id="example"></div>
<script type="text/babel">
	ReactDOM.render(
		<h1>Hello, world!</h1>,
		document.getElementById('example')
	);
</script>

</body>
</html>

方式三:搭建本地开发环境,通过 npm 使用 React

  • 环境要求: Node>= 10.16 和 npm >= 5.6

  • 使用 create-react-app 快速构建 React 开发环境

    $ cnpm install -g create-react-app
    $ create-react-app my-app
    $ cd my-app/
    $ npm start   // 运行本地服务
    

在浏览器中打开 http://localhost:3000/ 就能看到运行结果。

  • 项目的目录结构如下:
my-app/
  README.md
  node_modules/
  package.json
  .gitignore
  public/
    favicon.ico
    index.html
    manifest.json
  src/
    App.css
    App.js
    App.test.js
    index.css
    index.js
    logo.svg

manifest.json 指定了开始页面 index.html,一切的开始都从这里开始,所以这个是代码执行的源头。

React 元素渲染

将元素渲染到 DOM 中

首先我们在一个 HTML 页面中添加一个 id=“example” 的

,如下:

<div id="example"></div>

React 开发应用时一般只会定义一个根节点。

要将React元素渲染到根DOM节点中,我们通过把它们都传递给 ReactDOM.render() 的方法来将其渲染到页面上:

const element = <h1>Hello, world!</h1>;
ReactDOM.render(
    element,
    document.getElementById('example')
);

更新元素渲染

React 元素都是不可变的。当元素被创建之后,你是无法改变其内容或属性的。

目前更新界面的唯一办法是创建一个新的元素,然后将它传入 ReactDOM.render() 方法,比如下面这个定时器:

function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>现在是 {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  ReactDOM.render(
    element,
    document.getElementById('example')
  );
}
 
setInterval(tick, 1000);

ReactDOM.render调用函数及参数传递

  • ReactDOM.render内调用 已有函数与常规的JS有很大的区别:
    • 函数引用直接包含在</>中,而不是()
    • 多个参数是以key、value时直接传递的,而不是对象格式的date数据
    • 示例如下:
 ReactDOM.render(
      < functionname  property1 = {property1_value}  property2 = {property2_value} />,
       document.getElementById('example')
   );

以下实例用一个函数来表示前面的定时器封装:

function Clock(props){
    return (
        <div id={props.id}>
            <h1>Hello, {props.name} ~</h1>
            <h2>现在是北京时间 {props.date.toLocaleTimeString()}</h2>
        </div>
    )
}

function tick() {
    ReactDOM.render(
        < Clock date={new Date()} name={'world'} id={'world'}/>,
        document.getElementById('example')
    );
}

setInterval(tick, 1000);

值得注意的是 React DOM 首先会比较元素内容先后的不同,而在渲染过程中只会更新改变了的部分。

创建React.Component 的 ES6 类

需要注意的是在 render() 方法中,需要使用this.props 替换 props,示例:

class Clock extends React.Component{
    render(){
        return(
            <div id={this.props.id}>
                <h1>Hello, {this.props.name} ~</h1>
                <h2>现在是北京时间 {this.props.date.toLocaleTimeString()}</h2>
            </div>
        )
    }
}

function tick() {
    ReactDOM.render(
        < Clock date={new Date()} name='world' id='world'/>,
        {/* new Date() 这样的value,需要使用花括号来包含,仅字符串的值则不需要 */}
        document.getElementById('example')
    );
}

setInterval(tick, 1000);

React JSX

js和jsx的区别

既然这里提到了jsx,那就顺便了解一下两者的区别:

  • JS:即JavaScript,一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于浏览器客户端的脚本语言。
  • JSX: 即JavaScript XML——一种在React组建内部构建标签的类XML语法。(增强React程序组件的可读性)。Javascript和XML结合的一种格式。React发明了JSX,利用HTML语法来创建虚拟DOM。当遇到<,JSX就当HTML解析,遇到{就当JavaScript解析。

使用 jsx

React 实例

ReactDOM.render(
    <div>
	    <h1>React JSX</h1>
	    <h2>欢迎学习 React jsx</h2>
	    <p data-myattribute = "somevalue">这是一个很不错的 JavaScript 库!</p>
    </div>,
    document.getElementById('example')
);

jsx独立文件

  • 创建jsx独立文件:例如我们创建一个 helloworld_react.js 文件,代码如下:
ReactDOM.render(
	<h1>hello, world</h1>,
	document.getElementById('example')
)
  • 然后在 HTML 文件中引入该 JS 文件(注意:script type 为 text/babel):
<body>
  	<div id="example"></div>
	<script type="text/babel" src="helloworld_react.js"></script>
</body>

JavaScript 表达式

  • 在 JSX 中使用 JavaScript 表达式。表达式写在花括号 {} 中:
ReactDOM.render(
    <div>
      <h1>{1+1}</h1>
    </div>
    ,
    document.getElementById('example')
);
  • 条件判断语句:在 JSX 中不能使用 if else 语句,但可以使用 conditional (三元运算) 表达式来替代
ReactDOM.render(
 	<div>
      <h1>{i == 1 ? 'True!' : 'False'}</h1>
    </div>
    ,
    document.getElementById('example')
)

样式

React 推荐使用内联样式。我们可以使用 camelCase 小驼峰 语法来设置内联样式. React 会在指定元素数字后自动添加 px ,如font-size要写成fontSize:

let myStyle = {
	fontSize: 100,
	color: '#FF0000'
};
ReactDOM.render(
	<h1 style={myStyle}>hello, world {1+1}</h1>,
	document.getElementById('example')
)

注释

注释需要 写在花括号{} 中,实例如下:

ReactDOM.render(
	<h1>
		hello, world {1+1}
		{/*这是注释部分*/}
	</h1>,
	document.getElementById('example')
)

数组

JSX 允许在模板中插入数组,数组会自动展开所有成员:

let arr = [
	<h1>React教程</h1>,
	<h2>学的不仅是React,学的是方法。</h2>,
];
ReactDOM.render(
	<div>{arr}</div>,
	document.getElementById('example')
)

React 组件

实例解析:

function HelloMessage(props) {
	return <h1 className={props.class}>Hello {props.name}!</h1>;
}

const element = <HelloMessage class='testClass' name="Runoob"/>;

ReactDOM.render(
	element,
	document.getElementById('example')
);

注意:

  • 原生 HTML 元素名以小写字母开头,而自定义的 React 类名以大写字母开头,比如 HelloMessage 不能写成 helloMessage。除此之外还需要注意组件类只能包含一个顶层标签,否则也会报错。
  • 在添加属性时, class 属性需要写成 className ,for 属性需要写成htmlFor,这是因为 class 和 for 是 JavaScript 的保留字

复合组件

直接看例子吧:

function Name(props){
	return <h1>网站名称:{props.name}</h1>
}

function Url(props){
	return <h1>网站地址:{props.url}</h1>
}

function Nickname(props){
	return <h1>网站小名:{props.nickname}</h1>
}

function App(){
	return (
		<div>
			<Name name='React 复合组件学习'/>
			<Url url='http://www.runoob.com'/>
			<Nickname nickname={'React'}/>
		</div>
	)
}

ReactDOM.render(
	<App/>,
	document.getElementById('example')
);

React State(状态)

React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。
React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。

将生命周期方法添加到类中

在具有许多组件的应用程序中,在销毁时释放组件所占用的资源非常重要。

  • 挂载:每当 Clock 组件第一次加载到 DOM 中的时候,我们都想生成定时器,这在 React 中被称为挂载
  • 卸载:同样,每当 Clock 生成的这个 DOM 被移除的时候,我们也会想要清除定时器,这在 React 中被称为卸载

我们可以在组件类上声明特殊的方法,当组件挂载或卸载时,来运行一些代码:


class Clock extends React.Component {
	constructor(props) {
		super(props)
		this.state = {date: new Date()}
	}

	componentDidMount(){
		let _this = this;
		this.timerID = setInterval(function (){
			_this.tick()
		}, 1000)
	}

	componentWillUnmount() {
		clearInterval(this.timerID)
	}

	tick(){
		this.setState({
			date: new Date()
		})
	}

	render(){
		return(
			<div>
				<h1>Hello, world!</h1>
				<h2>现在是北京时间:{this.state.date.toLocaleTimeString()}</h2>
			</div>
		)
	}
}

ReactDOM.render(
	<Clock />,
	document.getElementById('example')
);

实例解析:

  • componentDidMount()componentWillUnmount() 方法被称作生命周期钩子。
  • 在组件输出到 DOM 后会执行 componentDidMount() 钩子,我们就可以在这个钩子上设置一个定时器。
  • 通过调用 setState(),React 知道状态已经改变,并再次调用 render() 方法来确定屏幕上应当显示什么。 这一次,render() 方法中的 this.state.date将不同,所以渲染输出将包含更新的时间,并相应地更新 DOM。
  • this.timerID 为定时器的 ID,我们可以在 componentWillUnmount()钩子中卸载定时器。

数据自顶向下流动

父组件或子组件都不能知道某个组件是有状态还是无状态,并且它们不应该关心某组件是被定义为一个函数还是一个类。
这就是为什么状态通常被称为局部或封装。 除了拥有并设置它的组件外,其它组件不可访问。
以下实例中 FormattedDate 组件将在其属性中接收到 date 值,并且不知道它是来自 Clock 状态、还是来自 Clock 的属性、亦或手工输入

function FormattedDate(props){
	return <h2>现在是北京时间:{props.date.toLocaleTimeString()}</h2>
}

class Clock extends React.Component {
	constructor(props) {
		super(props)
		this.state = {date: new Date()}
	}

	componentDidMount(){
		let _this = this;
		this.timerID = setInterval(function (){
			_this.tick()
		}, 1000)
	}

	componentWillUnmount() {
		clearInterval(this.timerID)
	}

	tick(){
		this.setState({
			date: new Date()
		})
	}

	render(){
		return(
			<div>
				<h1>Hello, world!</h1>
				<FormattedDate date={this.state.date}/>
			</div>
		)
	}
}

function App(){
	return(
		<div>
			<Clock />
			<Clock />
			<Clock />
		</div>
	)
}

ReactDOM.render(
	<App />,
	document.getElementById('example')
);

这里我还没有完全理解它的含义!

React Props

stateprops 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。

基本用法

前面的示例中都已经涉及到Props的使用,这里不再举例,只再提示一点普通类和ES6 class使用上的差别:

  • 普通的类:使用props.name 方式访问属性
  • ES6 类:使用this.props.name方式访问属性

State 和 Props

例:在父组件中设置 state, 并通过在子组件上使用 props 将其传递到子组件上。在 render 函数中, 我们设置 name 和 site 来获取父组件传递过来的数据

class Book extends React.Component{
	constructor(props) {
		super(props)

		this.state = {
			name: 'react',
			time: '2013年5月',
		}
	}

	render() {
		return (
			<div>
				<Name name={this.state.name}/>
				<Time time={this.state.time}/>
			</div>
		)
	}
}

class Name extends React.Component {
	render(){
		return(
			<h1>Book name: {this.props.name}</h1>
		)
	}
}

class Time extends React.Component {
	render(){
		return(
			<h1>Book create time: {this.props.time}</h1>
		)
	}
}

ReactDOM.render(
	<Book />,
	document.getElementById('example')
)

Props 验证

React.PropTypes 在 React v15.5 版本后已经移到了 prop-types 库。 React v15.5 版本以上使用时需要引入:<script src="https://cdn.staticfile.org/prop-types/15.6.1/prop-types.js"></script>

Props 验证使用 propTypes,它可以保证我们的应用组件被正确使用,React.PropTypes 提供很多验证器 (validator) 来验证传入数据是否有效。当向 props 传入无效数据时,JavaScript 控制台会抛出警告。

React 16.4 实例:

var title = "react learner";
class MyTitle extends React.Component {
	render() {
		return (
			<h1>Hello, {this.props.title}</h1>
		);
	}
}

MyTitle.propTypes = {
	title: PropTypes.string
};
ReactDOM.render(
	<MyTitle title={title} />,
	document.getElementById('example')
);

更多验证器说明如下

MyComponent.propTypes = {
    // 可以声明 prop 为指定的 JS 基本数据类型,默认情况,这些数据是可选的
   optionalArray: React.PropTypes.array,
    optionalBool: React.PropTypes.bool,
    optionalFunc: React.PropTypes.func,
    optionalNumber: React.PropTypes.number,
    optionalObject: React.PropTypes.object,
    optionalString: React.PropTypes.string,
 
    // 可以被渲染的对象 numbers, strings, elements 或 array
    optionalNode: React.PropTypes.node,
 
    //  React 元素
    optionalElement: React.PropTypes.element,
 
    // 用 JS 的 instanceof 操作符声明 prop 为类的实例。
    optionalMessage: React.PropTypes.instanceOf(Message),
 
    // 用 enum 来限制 prop 只接受指定的值。
    optionalEnum: React.PropTypes.oneOf(['News', 'Photos']),
 
    // 可以是多个对象类型中的一个
    optionalUnion: React.PropTypes.oneOfType([
      React.PropTypes.string,
      React.PropTypes.number,
      React.PropTypes.instanceOf(Message)
    ]),
 
    // 指定类型组成的数组
    optionalArrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
 
    // 指定类型的属性构成的对象
    optionalObjectOf: React.PropTypes.objectOf(React.PropTypes.number),
 
    // 特定 shape 参数的对象
    optionalObjectWithShape: React.PropTypes.shape({
      color: React.PropTypes.string,
      fontSize: React.PropTypes.number
    }),
 
    // 任意类型加上 `isRequired` 来使 prop 不可空。
    requiredFunc: React.PropTypes.func.isRequired,
 
    // 不可空的任意类型
    requiredAny: React.PropTypes.any.isRequired,
 
    // 自定义验证器。如果验证失败需要返回一个 Error 对象。不要直接使用 `console.warn` 或抛异常,因为这样 `oneOfType` 会失效。
    customProp: function(props, propName, componentName) {
      if (!/matchme/.test(props[propName])) {
        return new Error('Validation failed!');
      }
    }
  }
}

React 事件处理

  • React 事件绑定属性的命名采用驼峰式写法,而不是小写。

    <button onClick={activateLasers}>激活按钮</button>
    
  • 在 React 中另一个不同是你不能使用返回 false 的方式阻止默认行为, 你必须明确使用 preventDefault

    function ActionLink() {
      function handleClick(e) {
        e.preventDefault();
        console.log('链接被点击');
      }
     
      return (
        <a href="#" onClick={handleClick}>
          点我
        </a>
      );
    }
    

向事件处理程序传递参数

通常我们会为事件处理程序传递额外的参数。例如,若是 id 是你要删除那一行的 id,以下两种方式都可以向事件处理程序传递参数:

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>

通过 bind 方式向监听函数传参,在类组件中定义的监听函数,事件对象 e 要排在所传递参数的后面,例如:

class Popper extends React.Component{
    constructor(){
        super();
        this.state = {name:'Hello world!'};
    }
    
    preventPop(name, e){    //事件对象e要放在最后
        e.preventDefault();
        alert(name);
    }
    
    render(){
        return (
            <div>
                <p>hello</p>
                {/* 通过 bind() 方法传递参数。 */}
                <a href="https://reactjs.org" onClick={this.preventPop.bind(this,this.state.name)}>Click</a>
            </div>
        );
    }
}

【未完待续】

参考

标签:入门,render,React,PropTypes,props,组件,ReactDOM
来源: https://blog.csdn.net/qq_37116222/article/details/118083113

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有