React入门
元素与组件
使用CRA脚手架,一般src目录下的index.js目录是这样的
import React from 'react'; // 使用React API 支持jsx
import ReactDOM from 'react-dom'; // 渲染React元素到页面中
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
//ReactDOM.render(React元素,容器盒子)
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
其中定义了一个App变量,基本上我们的开发是在这个文件是做的,其又可以引入多种组件
函数式组件(无状态组件 PureComponent)
由于元素没有办法传递参数,所以我们就需要把之前定义的变量改为一个方法,让这个方法去return一个元素:
import React from 'react'
import ReactDOM from 'react-dom'
// 特别注意这里的写法,如果要在JSX里写js表达式(只能是表达式,不能流程控制),就需要加 {},包括注释也是一样,并且可以多层嵌套
const app = (props) => <h1>欢迎进入{props.name}的世界</h1>
ReactDOM.render(
app({
name: 'react'
}),
document.getElementById('root')
)
这里我们定义的方法实际上也是react定义组件的第一种方式-定义函数式组件,这也是无状态组件。但是这种写法不符合react的jsx的风格,更好的方式是使用以下方式进行改造
import React from 'react'
import ReactDOM from 'react-dom'
const App = (props) => <h1>欢迎进入{props.name}的世界</h1>
ReactDOM.render(
// React组件的调用方式
// <h1>欢迎进入React</h1>也可以,以元素创建
<App name="react" />,
document.getElementById('root')
)
import React from 'react'
function App ( props ) {
return (
<div>
<h3> React元素是一个函数 { props.name } </h3>
</div>
)
}
export default App
这样一个完整的函数式组件就定义好了。但要注意!注意!注意!组件名必须大写,否则报错。
class组件
ES6的加入让JavaScript直接支持使用class来定义一个类,react的第二种创建组件的方式就是使用的类的继承,ES6 class
是目前官方推荐的使用方式,它使用了ES6标准语法来构建
import React, { Component } from 'react';
class ClassComp extends Component{
render () { //render函数通过createElement 将jsx解析为VDOM对象模型,以供React Filber算法做比对
return (//jsx 唯一根元素
<div>
类组件
</div>
)
}
}
export default ClassComp
因为JS里没有真正的class,这个class只是一个语法糖, 但二者的运行机制底层运行机制不一样。
-
函数式组件是直接调用, 在前面的代码里已经有看到
-
es6 class
组件其实就是一个构造器,每次使用组件都相当于在实例化组件,像这样:import React from 'react' import ReactDOM from 'react-dom' class App extends React.Component { render () { return ( <h1>欢迎进入{this.props.name}的世界</h1> ) } } const app = new App({ name: 'react' }).render() ReactDOM.render( app, document.getElementById('root') )
React16版本之前的创建方法
// react 15.x
React.createClass({
render () {
return (
<div>{this.props.xxx}</div>
)
}
})
- 现在的项目基本上不用
React注释
import React, { Component } from 'react';
class ClassComp extends Component{
render () {
return (
<div>
类组件
{/* 我们采用es6 类来创建的组件 */}
</div>
)
}
}
export default ClassComp
组件的组合、嵌套【和Vue slot】
-
组件的嵌套: 将子组件在父组件的jsx中以标签的形式使用
-
组件的组合:将一个组件写在另一个组件的内容中,然后在外层组件中通过 this.props.children来接收内容中的组件
-
相对来说,更加推荐嵌套,更加方便清晰
-
将一个组件渲染到某一个节点里的时候,会将这个节点里原有内容覆盖
-
组件嵌套的方式就是将子组件写入到父组件的模板中去,且react没有Vue中的内容分发机制(slot),所以我们在一个组件的模板中只能看到父子关系
// 从 react 的包当中引入了 React 和 React.js 的组件父类 Component
// 还引入了一个React.js里的一种特殊的组件 Fragment
import React, { Component, Fragment } from 'react'
import Son from './Son'
class Father extends Component{
render () {
return (
<Fragment> //可以使外层少一层div
<h3> father组件 </h3>
<hr/>
<Son/> //组件的嵌套
</Fragment>
)
}
}
export default Father
- 组件的组合
import React,{ Fragment } from 'react'
import Content from './pages/Content'
import Banner from './pages/Banner';
class App extends Component{
render (){
return(
<Fragment>
<Content>
<Banner></Banner>
</Content>
</Fragment>
)
}
}
export default App
//```````````````````````````````````````````````````````````````````````````````````
//Content.js中内容
import React, { Component } from 'react';
class Content extends Component{
render () {
return (
<Container>
内容
{ this.props.children }
</Container>
)
}
}
export default Content
组件中DOM样式
一共有四种方式
-
行内样式
// 注意这里的两个括号,第一个表示我们在要JSX里插入JS了,第二个是对象的括号 <p style={{color:'red', fontSize:'14px'}}>Hello world</p>
行内样式需要写入一个样式对象,而这个样式对象的位置可以放在很多地方,例如
render
函数里、组件原型上、外链js文件中 -
使用class
React推荐我们使用行内样式,因为React觉得每一个组件都是一个独立的整体
其实我们大多数情况下还是大量的在为元素添加类名,但是需要注意的是,
class
需要写成className
(因为毕竟是在写类js代码,会收到js规则的限制,而class
是关键字)<p className="hello" style = {this.style}>Hello world</p>
-
不同的条件添加不同的样式
有时候需要根据不同的条件添加不同的样式,比如:完成状态,完成是绿色,未完成是红色。那么这种情况下,我们推荐使用classname/classnames这个包.
//需要安装这个包 import React, { Component } from 'react'; import classname from 'classname' class Content extends Component{ render () { return ( //React 样式添加第三种 classname / classnames <div className = { classname({ one: true, two: true, three: true })}> 内容 </div> ) } } export default Content
-
css-in-js ( 在js中写css )
styled-components
是针对React写的一套css-in-js框架,简单来讲就是在js中写css。npm链接styled-components是一个第三方包,要安装
React认为一切皆组件,那么样式也应该是一个组件
import React, { Component } from 'react'; import styled from 'styled-components' const Container = styled.section` background: #ccc; flex: 1; overflow: hidden; ` class Content extends Component{ render () { return ( //React 样式添加第四种 styled-components 样式组件 <Container> 内容 { this.props.children } </Container> ) } } export default Content
JSX 原理
要明白JSX的原理,需要先明白如何用 JavaScript 对象来表现一个 DOM 元素的结构?
看下面的DOM结构
<div class='app' id='appRoot'>
<h1 class='title'>欢迎进入React的世界</h1>
<p>
React.js 是一个帮助你构建页面 UI 的库
</p>
</div>
上面这个 HTML 所有的信息我们都可以用 JavaScript 对象来表示:
{
tag: 'div',
attrs: { className: 'app', id: 'appRoot'},
children: [
{
tag: 'h1',
attrs: { className: 'title' },
children: ['欢迎进入React的世界']
},
{
tag: 'p',
attrs: null,
children: ['React.js 是一个构建页面 UI 的库']
}
]
}
但是用 JavaScript 写起来太长了,结构看起来又不清晰,用 HTML 的方式写起来就方便很多了。
于是 React.js 就把 JavaScript 的语法扩展了一下,让 JavaScript 语言能够支持这种直接在 JavaScript 代码里面编写类似 HTML 标签结构的语法,这样写起来就方便很多了。编译的过程会把类似 HTML 的 JSX 结构转换成 JavaScript 的对象结构。
下面代码:
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
render () {
return (
<div className='app' id='appRoot'>
<h1 className='title'>欢迎进入React的世界</h1>
<p>
React.js 是一个构建页面 UI 的库
</p>
</div>
)
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
编译之后将得到这样的代码:
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
render () {
return (
React.createElement(
"div",
{
className: 'app',
id: 'appRoot'
},
React.createElement(
"h1",
{ className: 'title' },
"欢迎进入React的世界"
),
React.createElement(
"p",
null,
"React.js 是一个构建页面 UI 的库"
)
)
)
}
}
ReactDOM.render(
React.createElement(App),
document.getElementById('root')
)
React.createElement
会构建一个 JavaScript 对象来描述你 HTML 结构的信息,包括标签名、属性、还有子元素等, 语法为
React.createElement(
type,
[props],
[...children]
)
所谓的 JSX 其实就是 JavaScript 对象,所以使用 React 和 JSX 的时候一定要经过编译的过程:
JSX —使用react构造组件,babel进行编译—> JavaScript对象 —
ReactDOM.render()
—>DOM元素 —>插入页面