React.js笔记(入门)

React 是一个 JavaScript 库,使用了一些ES6语法。如:箭头函数, 类, 模板字符串, let, 和 const 声明。

React.JS的特点

  • 声明式设计 −React.JS采用声明范式,可以轻松描述应用。
  • 高效 −React.JS通过对DOM的模拟,最大限度地减少与DOM的交互。
  • 灵活 −React.JS可以与已知的库或框架很好地配合。
  • JSX − JSX 是 JavaScript 语法的扩展。React.JS开发不一定使用 JSX ,但建议使用它。
  • 组件 − 通过 React.JS构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
  • 单向响应的数据流 − React.JS实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单

1 React.js 的安装

React.js 的导入使用有两种方式,分别是使用 CDN 导入和使用 npm 的 create-react-app 导入。

  • 使用 CDN 导入,导入地址Demo页面如下:
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Hello React!</title>
    <!-- react.min.js - React 的核心库 -->
    <script src="https://cdn.bootcss.com/react/15.4.2/react.min.js"></script>
    <!-- react-dom.min.js -  提供与 DOM 相关的功能 -->
    <script src="https://cdn.bootcss.com/react/15.4.2/react-dom.min.js"></script>
    <!-- babel.min.js - Babel 可以将 ES6 代码转为 ES5 代码 -->
    <script src="https://cdn.bootcss.com/babel-standalone/6.22.1/babel.min.js"></script>
  </head>
  <body>
    <div id="example"></div>
    <!-- 要注意如果不添加 type="text/babel", 会报错 -->
    <script type="text/babel">
      ReactDOM.render(   
       <h1>Hello, world!</h1>,
        document.getElementById('example')
      );    
     </script>
  </body>
</html>
  • 使用 create-react-app 快速构建 React 开发环境

create-react-app 自动创建的项目是基于 Webpack + ES6 。
首先,全局安装 create-react-app

npm install -g create-react-app

然后在要创建项目的文件目录路径下,输入如以下语句用以初始化项目 “脚手架”

create-react-app [name]

最后启动以及生产最终项目文件的语法与 Vue 类似,分别是:

npm start

npm build

2 JSX

const element = <h1>Hello, world!</h1>;

查看上述这段代码,这种看起来既不是字符串变量也不是 HTML的东西,它被称为 JSX, 一种 JavaScript 的语法扩展。
JSX 用来声明 React 当中的 元素,推荐在 React 中使用 JSX 来描述用户界面。
JSX 乍看起来可能比较像是 模版语言,但事实上它完全是在 JavaScript 内部实现的。

JSX 本身其实也是一种表达式,在编译之后呢,JSX 其实会被转化为普通的 JavaScript 对象。

Babel 转译器会把 JSX 转换成一个名为 React.createElement() 的方法调用,即下面两种代码的作用是完全相同的:

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);
const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
);

2.1 JSX 中使用 Javascript 表达式

书写 JSX 时,可以使用 花括号 导入任意的 Javascript 表达式,同时在 JSX 代码的外面扩上一个小括号,这样可以防止 分号自动插入。如:

const element = (<p>Hello,{getName(user)}</p>);

2.2 JSX 属性

使用引号来定义以字符串为值的属性:

const element = <div tabIndex="0"></div>;

同样可以引入 Javascript 表达式,如:

const element = <div tabIndex={getIndex()}></div>;

JSX 的特性更接近 JavaScript 而不是 HTML , 所以 React DOM 使用 camelCase 小驼峰命名 来定义属性的名称,而不是使用 HTML 的属性名称。如,class 变成了 className,而 tabindex 则对应着 tabIndex

2.3 JSX 防注入攻击

你可以放心地在 JSX 当中使用用户输入,React DOM 在渲染之前默认会 过滤 所有传入的值。它可以确保你的应用不会被注入攻击。所有的内容在渲染之前都被转换成了字符串。这样可以有效地防止 XSS(跨站脚本) 攻击。

3 元素渲染

元素是构成 React 应用的最小单位,React 元素可以是用户自定义的组件

与浏览器的 DOM 元素不同,React 当中的元素事实上是普通的对象,React DOM 可以确保 浏览器 DOM 的数据内容与 React 元素保持一致。
如同 Vue.js 类似,首先要在 HTML 页面中寻找一个根DOM节点,而要将 React 元素渲染到根DOM节点中,需要通过把它们都传递给 ReactDOM.render() 的方法,来达到将其渲染到页面上的目的。如:

var element = (<p>Hello</p>);
ReactDOM.render(   
	element,
	document.getElementById('example')
);

3.1 更新元素渲染

与 Vue 不同,React 元素并不支持数据的双向绑定,当元素被创建之后,你是无法改变其内容或属性的。因此更新界面的办法是创建一个新的元素,然后将它传入 ReactDOM.render() 方法(或通过修改局部状态实现),如:

function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  ReactDOM.render(element, document.getElementById('root'));
}

setInterval(tick, 1000);

3.2 事件处理

React 元素的事件处理和 DOM元素的很相似,但是有一点语法上的不同:

  • React 元素事件绑定的事件名称是小驼峰命名
  • 采用 JSX 的语法你需要传入一个函数作为事件处理函数,而不是一个字符串(DOM元素的写法)

如 DOM 元素绑定写法是: onclick="clickTest()",而 React 元素事件绑定的写法是 onClick={clickTest}.

  • 在阻止默认行为的时候,比如点击链接后阻止它跳转,此时不能像 DOM 元素那样直接返回一个 false 值,需要显示地调用 e.preventDefault()

3.2.1 this 的绑定

同时还要注意的是 类的方法默认是不绑定 this 的,如果在没有绑定 this 的情况下,触发的事件方法使用了 this 的相关信息,返回的 this 是一个 undefined
而 React this 的绑定方式有几种:

class App extends React.Component {
        constructor(props) {
            super(props);
            this.checkThis3.bind(this);
        }
        checkThis1 = (e) => {
            console.log(e);
            console.log(this);
        }
        checkThis2(e) {
            console.log(e);
            console.log(this);
        }
        checkThis3(e) {
            console.log(e);
            console.log(this);
        }

        render() {
            return (
                <div>
                    <div onClick={this.checkThis1}>声明事件方法时使用了箭头函数,绑定事件时没有显式绑定this,此时正常输出this与e</div>
                    <div onClick={this.checkThis2}>正常普通形式地声明事件方法,绑定事件方法时没有显式绑定this,此时输出this为undefind,正常输出e</div>
                    <div onClick={this.checkThis2.bind(this)}>正常普通形式地声明事件方法,绑定事件方法时显式绑定了this,此时正常输出this与e</div>
                    <div onClick={(e) => {this.checkThis2(e)}}>正常普通形式地声明事件方法,绑定事件方法时使用箭头函数绑定,正常输出this,想要事件event对象,需要在箭头函数中显示传入e</div>
                    <div onClick={this.checkThis3}>正常普通形式地声明事件方法,在类的构造函数中显式绑定了this,正常输出this与e</div>
                </div>
            );
        }
    }

4 组件

React 的组件就等同于 Vue 的组件,从概念上像是函数,它可以接收任意的输入值(称之为 props),并返回一个需要在页面上展示的 React 元素

4.1 定义组件

React 定义组件有两个方式,分别为 函数定义 以及 类定义

  • 函数定义,如下例子,它接收一个单一的 props 对象并返回了一个 React 元素:
function Welcome(prop) {
	return <p>Hello, {prop.name}</p>
}
  • 类定义,可以使用 ES6 的 class 来定义一个组件,而使用 类定义 的组件比 函数定义 的组件会多一些额外的属性
class Welcome extends React.Component {
	render() {
		return <p>Hello, {this.prop.name}</p>
	}
}

值得注意的是与 Vue.js 一样,React 中组件的定义同样是只得一个根 DOM 包裹所有内容返回,另外 return 语句后最少要紧跟一个 ( 括号,不能直接换行

4.2 类定义组件的额外特性

使用类就允许我们使用其它特性,例如 局部状态生命周期钩子

4.2.1 局部状态 state

上述讲到,对比 Vue,React 无法通过修改 props 的数值从而直接对页面进行一个数据同步化处理,需要再次使用 ReactDOM.render 方法渲染组件。此外还可以通过修改局部状态来实现,而局部状态就是在类定义的组件的一个额外特性。
一些输入 DOM 如 input 标签的数据同步更新也是依赖这个局部状态,局部状态 state 看起来与 props 类似,类定义组件时,需要在 类构造函数 中进行一个初始化声明,如:

构造函数是唯一能够初始化 this.state 的地方

class Welcome extends React.Component {
	constructor(props) {
		this.props = props;
		this.state = {
			name: "Seiei"
		};
	}
	render() {
		return <h1>{this.state.name}</h1>
	}
}

想要更改 state,需要通过显式调用 this.setState 形如:

this.setState(
	{time: new Date()}
);

状态 stateprops 都是异步更新的,如下例子:

var Text = React.createClass({
            getInitialState: function() {
                return {name: "react"};
            },
            keyUp: function(e){
                this.setState({name: e.target.value});
                console.log(this.state.name);
            },
            render: function() {
                return (
                    <div className="a">
                        大家好,我是用{this.state.name}渲染出来的!
                        <input onKeyUp={this.keyUp} />
                    </div>
                );
            }
        });

在上述例子中,每次修改 input 标签的内容时,视图都会相应的同步更新,但在控制台中输出的内容却并不一定是对应的数值,这说明的是 state 状态的更新是异步,在控制台中输出的数值是异步还没执行完的数值。
要解决这个方法可以调用 this.setState 的重载方法,在第二个参数里传入同步处理的函数。
如修改为:

this.setState({name: e.target.value}, () => {console.log(this.state.name);});

当对原先状态进行一些类似自加减的行为时,可以修改为:

this.setState((prevState) => ({isToggleOn: !prevState.isToggleOn}));

注意:那个类似箭头函数,箭头后跟小括号而不是花括号

4.2.2 生命周期钩子

React 生命周期图
类似于 Vue 中的 createdbeforeMountmounted 这样的生命周期钩子,React 的声明周期钩子函数如上图。
每当组件第一次加载到 DOM 中,此时称为 挂载,每当组件生成的 DOM 被移除的时候,此时称为 卸载

同时由图可以看出,局部状态每次更新,需要更新页面的时候都会触发 render 函数。

4.3 条件渲染

跟 Vue 的条件渲染不同,React 的条件渲染没有关键字语法糖可以使用,React 的条件渲染跟 Javascript 条件判断一致,使用 Javascript 的 if 操作符或一些类如三元表达式来表示当前状态的元素,然后让 React 去渲染它们。
例如:

  • 在定义函数组件时,通过 if 操作符分别返回不同的 React 组件
  • render 方法中,声明一个元素变量,根据 if 操作符该变量的赋值也不同,最后将该变量进行一个返回
  • 直接使用三元表达式

想要进行一个隐藏、显示组件的切换。在 if 操作符中返回 null 而不是它的渲染结果即可实现。

4.4 列表渲染

同样的相对Vue.js,React 的列表渲染同样没有关键字、语法糖可以使用。使用的是 类似 Javascript 中的 map() 函数,例如:

function UserComponent(props) {
	return (
		<ul>
			{props.users.map((item, index) => 
				(<li key={index}>{item.name}</li>)
			)}
		</ul>
	);
}

class App extends React.Component {
	userList = [{name: "Seiei"}, {name: "Taka"}]
	render: function() {
		return (
			<div>
				<UserComponent users={this.userList}/>
			</div>
		);
	}
}

但如同 Vue.js 一样,当循环创造元素时,需要该这个元素赋予一个特殊的 Key 属性,Key 可以在DOM中的某些元素被增加或删除的时候帮助React识别哪些元素发生了变化。因此你应当给数组中的每一个元素赋予一个确定的标识,可以使用序列号索引作为 key 值。
当要注意的是:元素的key只有放在其环绕数组的上下文中才有意义,也就是是说如果 key 值是定义在循环元素之下的元素时,此时的 key 值是没有意义的,最好的方法就是 key 值定义在 map 方法中。

注意:React 的 map() 方法箭头后跟的无需花括号

4.5 受控组件

受控组件就是 React 中的用户输入元素,实质就是使用 state 局部状态达到数据双向同步更新的效果,如:

class NameInput extends React.Component {
	constructor(props) {
		super(props);
    	this.state = {value: ''};
    	this.handleChange.bind(this);
	}
	handleChange(event) {
    	this.setState({value: event.target.value});
  	}
  	render() {
		return (
			<div>
				<input value={this.state.value} onChange={this.handleChange} />
			</div>
		)
	}
}

4.6 状态提升

如同 Vue.js 一样,有时候组件之间需要共用相同的数据源,这时候除了引入使用一些状态管理插件。最原始的方法就是将这些状态数据提升到他们最近的 父组件 当中进行管理。
此时,父组件可以将修改 state 状态的方法通过 props 属性传递给子组件,子组件便可以通过该方法从而能修改父组件中的 state 状态值。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值