React.js初探
React.js
菜鸟官方解释:
React 是一个用于构建用户界面的 JAVASCRIPT 库。
React主要用于构建UI,很多人认为 React 是 MVC 中的 V(视图)。
React 起源于 Facebook 的内部项目,用来架设 Instagram 的网站,并于 2013 年 5 月开源。
React 拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它
React特点:
1.声明式设计 −React采用声明范式,可以轻松描述应用。
2.高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。
3.灵活 −React可以与已知的库或框架很好地配合。
4.JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。
5.组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。
6.单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。
Virtual Dom
state创建数据
jsx 模板
数据 + 模板 生成Virtual DOM(虚拟节点就是js创建的一个对象,该对象是对节点的一个描述,包含了该节点的所有信息,attrs,content等)
用虚拟DOM生成真实的DOM,显示
state改变
数据 + 模板生成新的 Virtual DOM
对比新旧Virtual DOM的区别,找到区别。
直接操作DOM改变有区别的地方。
注:因为浏览器在解析网页时,js和html是分开的。就相当于两个模块,js要跨越界限操作别人的东西,所以说代价是比较大的。虚拟dom的创建使得性能很大程度提升,且他的应用 使得跨端应用得意实现 React Native.在android和ios端是不存在dom一说的,所以在创建虚拟dom后,会将虚拟dom生成对应的原生的东西。
Progressive Web Application
字义即:渐进式Web应用
PWA有可以实现什么呢?
可以将app的快捷方式放置到桌面上,全屏运行,与原生app无异
能够在各种网络环境下使用,包括网络差和断网条件下,不会显示undefind
推送消息的能力
其本质是一个网页,没有原生app的各种启动条件,快速响应用户指令
在React.js中。public文件夹下有一个mainfest.json的文件夹,该文件就是用来实现桌面快捷方式的配置,而无网络情况,或网络情况较差时,则使用service worker来实现离线缓存。
Service Worker
Web离线引用解决方案。指在在进过网页后,当网络断开连接后,依然可以再次访问页面。
ServiceWorker的主要能力集中在网络代理和离线缓存上。具体的实现上,可以理解为ServiceWorker是一个能在网页关闭时仍然运行的WebWorker
在通过react脚手架创建项目后,src根目录下是有一个serviceWorker.js文件的,该文件就是用来写app时,提供离线缓存技术。供线下仍可正常访问。
Immutable
保证state中的数据不被修改。修改数据时,不能通过this.state.xx来就该数据需要用特定的方法this.setState({});可以发现和小程序也是一样的了
JSX
百度解释:
JSX是一种JavaScript的语法扩展,运用于React架构中,其格式比较像是模版语言,但事实上完全是在JavaScript内部实现的。元素是构成React应用的最小单位,JSX就是用来声明React当中的元素,React使用JSX来描述用户界面。
详细使用:JSX
render() {
return (
<div>
<ul>
<li></li>
</ul>
</div>
)
}
上面代码等同于下面
render() {
return React.createElement('div',{},React.createElement('ul',{},React.craeteElement('li',{})));
}
他的顺序:jsx => createElement => Virtual Dom => 真实Dom
vue和react的虚拟节点的渲染其实是一致的
className
在设置样式时,我们原来都是通过添加class或者id来设置对应的类名,在react中因为创建模板时使用的就是class类,所以在渲染模板时,样式的设置可以通过className=""来设置
Fragment
每个组件都要求有大的标签包裹,但是会产生不必要的DOM,因此react提供了Fragment来坐占位符。这样就不会产生新的节点,且组件不会抱任何错误。
import React, { Component,Fragment } form 'react';
class Demo extends Component {
render() {
return (
<Fragment>
Html content
</Fragment>
)
}
}
dangerouslySetInnerHTML
在render中如果要使某些内容不被转义。
则我们就需要使用dangerouslySetInnerHTML来保持元素不被转义
<div dangerouslySetInnerHTML={{ __html: '<div>123</div>' }} />
dangerouslySetInnerHTMl 是React标签的一个属性,类似于angular的ng-bind;
有2个{{}},第一{}代表jsx语法开始,第二个是代表dangerouslySetInnerHTML接收的是一个对象键值对;
既可以插入DOM,又可以插入字符串;
但是存在一个问题,因为使用标签内容后会将其转换,所以很有可能遭到XSS攻击。
import React,{ Component,Fragment } from 'react';
import './style/todoList.css' class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: '',
list: []
}
this.handleInputChange = this.handleInputChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
render() {
return (
<Fragment>
{/**这里是注释 */}
<input
className="input"
onChange={this.handleInputChange.bind(this)}
value={this.state.inputValue}
/>
<button className="btn" onClick={this.handleSubmit}>提交</button>
<ul>
{
this.state.list.map((item,index) => {
return (
<li
key={index}
onClick={this.handleDeleteItem.bind(this,index)}
dangerouslySetInnerHTML={{__html:item}}
>
</li>
)
})
}
</ul>
</Fragment>
)
};
handleInputChange(e) {
this.setState({
inputValue: e.target.value
})
};
handleSubmit() {
this.setState({
list: [...this.state.list,this.state.inputValue],
inputValue: ''
})
};
handleDeleteItem(index) {
let list = [...this.state.list];
list.splice(index,1);
this.setState({
list: list
})
}
}
export default TodoList;
当我们在input中输入<h1>Hello World</h1>时,如果使用了dangerouslySetInnerHTML的话,h1标签就会生效。
htmlFor
在使用label时,一般我们会通过for与input上的id进行绑定。在react中,我们则需要通过htmlFor=""来绑定input
组件传值
父传子
父传子通过属性传递,将需要传递的数据放在子组件上,通过属性的方式传递,子组件通过this.props.attr则就可以获取到父组件传递过来的数据
父组件:
import TodoItem from './TodoItem'
render() {
return (
<ul>
{
this.state.list.map((item,index) => {
return (
<div>
<TodoItem content={item} index={index} />
{/*<li
key={index}
onClick={this.handleItemDelete.bind(this,index)}
dangerouslySetInnerHTML={{__html:item}}
>
</li>*/}
</div>
)
})
}
</ul>
)
}
给子组件将数据挂在到content和index上,
子组件的获取
import React, { Component } from "react"; class TodoItem extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
render() {
return (
<div>{this.props.content}</div>
)
}
} export default TodoItem;
通过this.props就可以获取到父组件传递过来的数据。
子传父
子传父的话,没有vue那么多的方法,这里需要在父组件先将方法传递给子组件。
子组件调用父组件更改数据的方法。获取将数据作为方法的参数调用传递给父组件的方法就可以。
将方法通过属性的方式挂在到子组件上,不过需要注意的是,这里需要绑定指向为父组件
还是刚才的内容
import React,{ Component,Fragment } from 'react';
import TodoItem from './TodoItem';
import './style/todoList.css'; class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: '',
list: []
}
this.handleInputChange = this.handleInputChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleItemDelete = this.handleItemDelete.bind(this);
}
render() {
return (
<Fragment>
<div>
<label htmlFor="inputArea">输入内容</label>
<input
id="inputArea"
className="input"
onChange={this.handleInputChange}
value={this.state.inputValue}
/>
<button
className="btn"
onClick={this.handleSubmit}
>提交</button>
</div>
<ul>
{this.getTodoItem()}
</ul>
</Fragment>
)
};
getTodoItem() {
return this.state.list.map((item,index) => {
return (
<TodoItem
key={index}
content={item}
index={index}
deleteItem={this.handleItemDelete}
/>
)
})
}; handleInputChange(e) {
const value = e.target.value;
this.setState(() => ({
inputValue: value
}))
};
handleSubmit() {
this.setState((prevState) => ({
list: [...prevState.list,prevState.inputValue],
inputValue: ''
}))
};
handleItemDelete(index) {
this.setState((prevState) => {
const list = [...prevState.list];
list.splice(index,1);
return {list}
})
}
}
export default TodoList;
deleteItem就是挂在的方法,供子组件调用
子组件
import React, { Component } from "react"; class TodoItem extends Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
render() {
const { content }= this.props;
return (
<div onClick={this.handleClick}>
{content}
</div>
)
}
handleClick() {
const { deleteItem,index } = this.props;
deleteItem(index);
}
} export default TodoItem;
注:react是单向数据流,举这样一个例子:父组件引用了5个子组件,每个子组件都引用了父组件传递的list.如果不是单向数据流,子组件在对this.props.list= [];做出修改后,其他4个子组件会怎样?
显示这就是一个bug了,修改一个其他的都修改了。显然是一个比较严重的问题。所以react单向数据里就是解决这样一个问题。
父组件传递给子组件的数据,是无法做出修改的。state中的数据有一个只读属性,是无法做出修改的。如果非要修改,需要父组件传递给子组件一个方法,子组件通过调用该方法来实现数据的更改。
setState
该方法用来更新state数据,调用该方法时,就算state中的数据没有做修改,也会重新执行render方法。
setState({
isActive: true,
})
console.log(this.state.isActive)//false
该方法其实是一个异步操作,所以要得到最新的state需要在第二个参数回调函数中获取或者通过async和await来解决啦
async handleClick() {
await this.setState({
isActive: true
})
console.log(this.state.isActive);//true
}
该方法有两个参数
setState((prevState) => {
//prevState是旧的数据
},()=> {
//这里可以得到更新以后的数据
})
PropTypes
组件间传值时,对接受数据的一个限制
详细doc可查看官网https://reactjs.org/docs/typechecking-with-proptypes.html
import { PropTypes } from 'prop-types'
class 组件 extends Component {}
组件.propTypes = {
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,
}
isRequired
要求该传值对象不能为空,必须有值
组件.propTypes = {
obj: PropTypes.string.isRequired
}
arrayOf()
要求类型可以为多项
组件.propTypes = {
obj: PropTypes.arrayOf(PropTypes.number,PropTypes.string)
}
defaultProps
为组件间传值的对象设置默认值
class 组件 extends Component {}
组件.defaultProps = {
obj1: 'hello world'
}
设置默认值后,父组件在未传递数据时,会默认使用该默认值
后续继续学习更新
React.js初探的更多相关文章
- React.js初探(一)
前端框架多如牛毛的今天,团队的技术选型很重要,没有最好的,只有最合适的,这话早已经被说烂了. 但是作为一个有追求的前端,对新技术的敏感以及尝试心理还是要有的. 虽然React已经火的不行了,但由于自己 ...
- MVC、MVP、MVVM、Angular.js、Knockout.js、Backbone.js、React.js、Ember.js、Avalon.js、Vue.js 概念摘录
注:文章内容都是摘录性文字,自己阅读的一些笔记,方便日后查看. MVC MVC(Model-View-Controller),M 是指业务模型,V 是指用户界面,C 则是控制器,使用 MVC 的目的是 ...
- React Native初探
前言 很久之前就想研究React Native了,但是一直没有落地的机会,我一直认为一个技术要有落地的场景才有研究的意义,刚好最近迎来了新的APP,在可控的范围内,我们可以在上面做任何想做的事情. P ...
- 再谈React.js实现原生js拖拽效果
前几天写的那个拖拽,自己留下的疑问...这次在热心博友的提示下又修正了一些小小的bug,也加了拖拽的边缘检测部分...就再聊聊拖拽吧 一.不要直接操作dom元素 react中使用了虚拟dom的概念,目 ...
- React.js实现原生js拖拽效果及思考
一.起因&思路 不知不觉,已经好几天没写博客了...近来除了研究React,还做了公司官网... 一直想写一个原生js拖拽效果,又加上近来学react学得比较嗨.所以就用react来实现这个拖 ...
- React.js深入学习详细解析
今天,继续深入学习react.js. 目录: 一.JSX介绍 二.React组件生命周期详解 三.属性.状态的含义和用法 四.React中事件的用法 五.组件的协同使用 六.React中的双向绑定 ...
- React.js入门必须知道的那些事
首先,React.js是facebook在2013年5月开源的一个前端框架,React不是一个MVC框架,它是构建易于可重复调用的web组件,侧重于UI, 也就是view层, React为了更高超的性 ...
- React.js 官网入门教程 分离文件 操作无法正常显示HelloWord
对着React官网的教程练习操作,在做到分离文件练习时,按照官网步骤来却怎么也无法正常显示HelloWord. 经测试,html文件中内容改为: <!DOCTYPE html><ht ...
- React.js入门笔记(再续):评论框的实现
本案例来自React.js中文官网对应内容. 一. 运行环境 <link rel="stylesheet" type="text/css" href=&q ...
随机推荐
- 惊了!!! 小白零基础学java (月薪过万是你的梦想嘛) 手把手教学 就怕你不动手【二十五】第二章【初识MySQL】
初识MySQL1. 了解主流的数据库和数据库分类1.1 数据库概念数据库:按照数据结构来组织.存储和管理数据的一种建立在计算机存储设备上的仓库. 数据库的优势: 1. 可以持久化存储大量的数据.方便我 ...
- c++ map: 当map的value是void*指针
#include <iostream> #include <map> #include <vector> using namespace std; //key is ...
- 一个带关闭按钮的Div窗口,很漂亮
<html><head><title>JS+CSS实现带关闭按钮的DIV弹出窗口</title><script> function lock ...
- (C/C++学习)12.获取系统时间制作时钟(system()略解)
说明:通过调用函数来获取系统当前时间,并制作一个数字式的时钟,时钟的显示包括年.月.日.小时.分以及秒,通过系统屏幕的刷新来对不断更新的时间进行屏幕的显示. 一.对相关函数的学习 1.time_t t ...
- H5 web存储
H5提供了两种在客户端存储数据的方式:localStorage 持久化的本地存储(浏览器关闭重新打开数据依然存在)sessionStorage 针对一个session的本地存储之前这些都是由cooki ...
- pyhon中的内存优化机制
一.变量的内存地址 python中变量的内存地址可以用id()来查看 >>> a = " >>> id(a) 2502558915696 二.pyhon中 ...
- BUAA_OO_博客作业一
BUAA_OO_博客作业一 (一)程序结构分析 1.代码统计 第一次作业 第二次作业 第三次作业 代码复杂度展示第三次作业的 method ev(G) iv(G) v(G) Constant.Cons ...
- UVa - 11452 - Dancing the Cheeky-Cheeky
先上题目: F. Dancing the Cheeky-Cheeky Context The Cheeky-Cheeky is a new song. They dance it in Mula, ...
- GMT,UTC,DST,CST时间详解
全球24个时区的划分 相较于两地时间表,可以显示世界各时区时间和地名的世界时区表(World Time),就显得精密与复杂多了,通常世界时区表的表盘上会标示着全球24个时区的城市名称,但究 ...
- Blue Jeans POJ 3080 寻找多个串的最长相同子串
Description The Genographic Project is a research partnership between IBM and The National Geographi ...