企业网站建设论文文献综述,html在线编写网站,所有网站排名2015年,开发区网站建设的目的学习目标安装create-react-app脚手架熟练React基础语法掌握JSX语法掌握setState掌握React生命周期掌握props传递参数掌握React组件通信资源reactcreate-react-app 起步上手npm i -g create-react-app 安装官方脚手架create-react-app 01_react 初始化react的api比较少,基本学习…学习目标安装create-react-app脚手架熟练React基础语法掌握JSX语法掌握setState掌握React生命周期掌握props传递参数掌握React组件通信资源reactcreate-react-app 起步上手npm i -g create-react-app 安装官方脚手架create-react-app 01_react 初始化react的api比较少,基本学习一次就再也不用再看文档它的核心是JSReactReactDOMReact只做逻辑层,reactDOM去渲染真实的DOM删除src下面所有代码,新建index.jsimport React from react;
import ReactDOM from react-dom;
import App from ./App
ReactDOM.render(App /,document.querySelector(#root))新建 App.jsimport React from react
class App extends React.Component {render() {return (divhello,小马哥/div)}
}
export default App;以上代码感觉都没有问题,但是发现了一个很有趣的标签语法,它既不是字符串也不是HTML它被称为JSX,是一个JavaScript的语法扩展.我们建议在 React 中配合使用 JSXJSX 可以很好地描述 UI 应该呈现出它应有交互的本质形式。JSX 可能会使人联想到模版语言但它具有 JavaScript 的全部功能。JSX在JavaScript中直接写的标签,是一个JSX(JSXML,由于HTML也是XML的一种,可以认为JSHTML)元素,也是一个react元素,这个元素实际是一个对象,就是虚拟DOM元素React 认为渲染逻辑本质上与其他 UI 逻辑内在耦合.比如在 UI 中需要绑定处理事件、在某些时刻状态发生变化时需要通知到 UI以及需要在 UI 中展示准备好的数据。import React, { Component } from reactimport logo from ./favicon.ico
const ele h2hello,world/h2
function formatName(user) {// 也可以是个表达式return user.firstName user.lastName;
}
const user {firstName: 张,lastName: 三丰
}//jsx也可以是表达式
function getGreeting(user) {if (user) {return h1hello {formatName(user)}/h1}return h1hello,小马哥/h1
}
export default class App extends Component {render() {return (div{ele}{/* jsx运算 */}{2 1}br /{/*jsx嵌入表达式*/}{formatName(user)}{/* 添加属性 */}img src{logo} alt //div// getGreeting())}
}强烈建议大家阅读官网,针对React.render()内部的实现操作 元素渲染元素是构成React应用的最小砖块,比如:const ele h1hello,world/h1 与浏览器的 DOM 元素不同React 元素是创建开销极小的普通对象。React DOM 会负责更新 DOM 来与 React 元素保持一致上节课的ReactDOM.render()其实就是在渲染DOM节点更新已渲染的元素React元素是不可变对象,一旦被创建,无妨更改它的子元素或者属性计时器的例子function tick() {const element (divh1Hello, world!/h1h2{new Date().toLocaleTimeString()}./h2/div);ReactDOM.render(element, document.querySelector(#root));
}setInterval(tick, 1000);大多数情况下,React应用只会调用一次ReactDOM.render()React只需要更新它需要更新的部分React DOM会将元素和它的子元素与它们之前的状态进行比较,并只会进行必要的更新来使DOM达到预期的状态循环绑定元素当数据从后端请求回来之后,在React中,一般都需要循环绑定元素map绑定在React中,循环绑定元素都是使用map方法,不能使用forEach是因为forEach没有返回值let ul (ul{ arr.map((item, index){return li key{index}{item}/li}) }
/ul);结果会是一个 JSX 元素组成的数组放入页面中不会使用逗号分隔开。循环绑定的 JSX 元素必须要有 key 属性来区分不同的元素否则会报错。过滤元素同样通过map方法,只要把不符合条件的元素,返回为null即可,原因在于,null会被表示为空.如果使用filter,那么就没有办法对元素进行处理,只能过滤,还是需要使用map进行处理let ul (ul{ arr.map((item, index){return (item.price 1000 ? null : li key{index}{item}/li;)}) }
/ul)ref和refs在React中,类似于Vue,可以通过ref标记元素,然后通过this.refs获取元素,只是Vue中使用的是this.$refs获取元素字符串写法通过设置一个字符串值来标记元素,然后通过这个字符串作为属性获取元素class Input extends Component {handleChange (e) {console.log(this.refs.a.value)}render() {return (divinput typetext refa onChange{this.handleChange} //div)}
}函数写法函数作为一个ref的属性值,这个函数接受一个参数,就是真实的DOM元素可以把这个元素挂载到实例上,方便后面的操作class Input extends React.Component {componentDidMount() {console.log(this.a); //获取真实的DOM元素}render() {return (divinput typetext ref{xthis.a x}/ /div);}
}组件propsReact创建组件有来两种方式函数声明类声明React组件特点:组件名称应该首字母大写,否则会报错组件定义之后,可以像JSX元素一样使用必须使用render函数才能将虚拟DOM渲染成真实的DOM使用组件时,可以使用单标签,也可以使用双标签函数组件组件从概念上类似于 JavaScript 函数。它接受任意的入参即 “props”并返回用于描述页面展示内容的 React 元素。函数声明的组件,必须返回一个JSX元素可以通过属性给组件传递值,函数通过props参数属接收定义组件最简单的方式就是编写JavaScript函数function Welcome(props){return h2hello,{props.name}/h2
}我们称为该组件为函数组件,因为它本质上就是一个函数类声明组件使用ES6的class的方式定义组件类声明组件需要注意在React中有一个属性Component,是一个基类,使用类声明组件时,必须继承这个基类在类中,必须有render函数,constructor不是必须的在render函数中**,需要return一个JSX元素**class Welcome extends Component {render() {return (// 它会将 JSX 所接收的属性attributes转换为单个对象传递给组件这个对象被称之为 “props”。h2Welcome,{this.props.name}/h2);}
}注意 组件名称必须以大写字母开头。 React会将小写字母开头的组件称之为标签例如,div /代表HTML的div标签,而Welcome /则代表一个组件,并且需在作用域内使用Welcome两种方式的区别真实项目中,都只使用class定义组件class定义的组件中有this,状态,生命周期function声明都没有组合组件组件可以输出的时候嵌入其他的组件。这就可以让我们用同一组件中来抽离出任意层次的细节(复用组件)。按钮表单对话框甚至整个屏幕的内容在 React 应用程序中这些通常都会以组件的形式表示。什么是复合组件:将多个组件进行组合,例如调用两次相同的组件结构非常复杂时需要将组件拆分成小组件会存在父子关系的数据传递import React, { Component } from react;
import ReactDOM from react-dom;class Welcome extends Component {render() {return (divh3Welcome,{this.props.name}/h3/div);}
}
class App extends Component {render() {return (divWelcome name张三/WelcomeWelcome name李四/WelcomeWelcome name王五/Welcome/div)}
}
// 组合组件
ReactDOM.render(App/App,document.querySelector(#root));可想而知,React开发其实就是组件化开发,因为React真的是组件化开发的鼻祖提取组件将组件拆分成更小的组件import React, { Component } from react;
import ReactDOM from react-dom;// 所有props是只读的,不能直接修改
class Avatar extends Component {render() {return (img src{this.props.user.avatarUrl} alt{this.props.user.name} /);}
}class UserInfo extends Component {constructor(props) {super(props);console.log(this.props);}render() {return (div classNameuserinfoAvatar user{this.props.user}/Avatardiv classNameusernameh3{this.props.user.name}/h3/div/div);}
}class Comment extends Component {constructor(props) {super(props);}render() {return (div classNamecommentUserInfo user{this.props.user}/UserInfodiv classNameComment-text{this.props.user.text}/divdiv classNameComment-date{this.props.user.date}/div/div);}
}
class App extends Component {constructor() {super();this.user {avatarUrl: https://hcdn1.apeland.cn/media/course/icon2.png,name: 张三,text: hello,React component,date: new Date().toLocaleString()}}render() {return (divComment user{this.user}/Comment/div)}
}
// 组合组件
ReactDOM.render(App/App,document.querySelector(#root));最初看上去提取组件可能是一件繁重的工作但是在大型应用中构建可复用组件库是完全值得的。 根据经验来看如果 UI 中有一部分被多次使用ButtonPanelAvatar或者组件本身就足够复杂AppComment那么它就是一个可复用组件的候选项。你说对吧!父子组件通信父传子父组件通过行间属性传递数据到子组件,子组件通过实例上的props属性接收新的数据React 的数据是单向数据流只能一层一层往下传递。当组件的属性发生改变那么当前的视图就会更新子传父通过给子组件传递一个函数子组件调用父亲的函数将值作为参数传递给父组件父组件更新值刷新视图。父组件中定义一个函数通过属性传递给子组件。这个传递的函数必须是一个箭头函数import React, { Component } from react;
import ReactDOM from react-dom;class ChildCom extends Component {constructor(props) {super(props);console.log(props);this.state {val:}this.handlerClick this.handlerClick.bind(this);this.handlerChange this.handlerChange.bind(this);}handlerChange(event){this.setState({val: event.target.value})}handlerClick(){if(this.state.val){this.props.addHandler(this.state.val);// 清空输入框this.setState({val: })}}render() {return (divinput typetext value {this.state.val} onChange {this.handlerChange}/button onClick{this.handlerClick}添加/button{this.props.menus.map((item,index) {return p key {index}{item}/p})}/div);}
}class App extends Component {constructor(props) {super(props);this.state {menus: [烤腰子, 辣炒鸡丁, 炸黄花鱼]}}// 一定要使用箭头函数addHandler (val){this.state.menus.push(val);this.setState({menus:this.state.menus})}render() {// 修改状态之后,会重新调用renderreturn (divChildCom menus{this.state.menus} addHandler {this.addHandler}/ChildCom/div);}
}ReactDOM.render(App /, document.querySelector(#root));Props的只读性组件无论是使用函数声明还是通过 class 声明都决不能修改自身的 props//该函数不会尝试更改入参且多次调用下相同的入参始终返回相同的结果。
function sum(a, b) {return a b;
}
//它更改了自己的入参
function withdraw(account, amount) {account.total - amount;
}所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。state组件状态组件中数据的来源属性:是由外接传递过来的状态:是自己的,只能通过setState来改变状态只有类声明的组件中,才有状态修改状态除了constructor之外的其它地方,如果需要修改状态,都只能通过this.setState方法这个方法传入的第一个参数,可以是一个对象,也可以是一个函数是一个对象这个对象中包含需要改变的属性它会与原有的状态进行合并是一个函数接收第一个参数是 prevState上一个状态对象第二个参数是 props 这个方法的第二个参数是一个回调函数在状态改变之后执行。如果下一个状态依赖于上一个状态需要写成函数的方式关于setState在 react 组件的生命周期或事件的绑定中setState 是异步的在定时器或原生的事件中setState 不一定是异步的// state.count 当前为 0
componentDidMount(){this.setState({count: this.state.count 1});console.log(this.state.count)
}
// 输出 0在元素渲染章节中我们只了解了一种更新 UI 界面的方法。通过调用 ReactDOM.render() 来修改我们想要渲染的元素function tick() {const element (divh1Hello, world!/h1h2{new Date().toLocaleTimeString()}./h2/div);ReactDOM.render(element, document.querySelector(#root));
}setInterval(tick, 1000);本节学习如何封装真正可复用的Clock组件import React, { Component } from react;
import ReactDOM from react-dom;// 学习如何封装真正可复用的Clock组件。
class Clock extends Component {constructor(props) {super(props);this.state {date: new Date().toLocaleString()}}componentDidMount() {this.timer setInterval(() {// 注意1 不能直接修改state// this.state.date new Date(); //错误// 注意2 setState()是异步的this.setState({date: new Date().toLocaleString()})}, 1000);}componentWillUnmount() {clearInterval(this.timer);}render() {// 修改状态之后,会重新调用renderreturn (divh3当前时间为:{this.state.date}/h3/div);}
}ReactDOM.render(Clock /, document.querySelector(#root));生命周期当然react16.x之后又更新了新的生命周期方法。如图React生命周期主要包括三个阶段初始化阶段、运行中阶段和销毁阶段在React不同的生命周期里会依次触发不同的钩子函数下面我们就来详细介绍一下React的生命周期函数import React, { Component } from react;
import ReactDOM from react-dom;class SubCounter extends Component {// 组件将要接收属性componentWillReceiveProps(newProps){console.log(9.子组件将要接收到新属性,newProps);}shouldComponentUpdate(newProps,newState){console.log(10.子组件是否需要更新)if(newProps.num % 3 0){return true;}else{return false;}}componentWillUpdate() {console.log(11、子组件将要更新);}componentDidUpdate() {console.log(13、子组件更新完成);}componentWillUnmount() {console.log(14、子组件将卸载);}render() {console.log(12.子组件挂载中)return (divp{this.props.num}/p /div);}
}class Counter extends Component {static defaultyProps {//1.加载默认属性name:小马哥,age:18}constructor(props) {super(props);//2.记载默认状态this.state {num: 0}}componentWillMount() {// 此时可以访问属性和状态可以进行api调用但没办法做DOM相关操作console.log(3.父组件将要被挂载);}componentDidMount() {// 组件已挂载可进行状态更新操作。通常 都在此方法中发送请求console.log(5.组件挂载完成);}shouldComponentUpdate(newProps, newState) {// 组件是否需要更新返回布尔值优化点console.log(6.父组件是否被更新);// console.log(newProps, newState);if (newState.num % 2 0) {return true;} else {// 此函数 会返回一个boolean值,返回true更新页面,返回false不更新页面return false;}}componentWillUpdate(){console.log(7.父组件将要更新);}componentDidUpdate(){console.log(8.父组件更新完成);}handlerClick () {// 可能,只是说可能,官网上都是这样说的.......会导致计数可能不准确,// this.setState({// num: parseInt(this.props.increment) this.state.num// })// 发现点击之后,得到的结果为0,这是因为setState()是异步的// console.log(this.state.num);// 要解决这个问题可以让 setState() 接收一个函数而不是一个对象。// 这个函数用上一个 state 作为第一个参数将此次更新被应用时的 props 做为第二个参数this.setState((state, props) {return {num: state.num parseInt(props.increment)}}, () {console.log(this.state.num);})}render() {// 修改状态之后,会重新调用renderconsole.log(4.render(父组件)渲染了);return (divh3当前数值:{this.state.num}/h3button onClick{this.handlerClick}1/buttonh3我是子组件/h3SubCounter num {this.state.num}/SubCounter/div);}
}ReactDOM.render(Counter increment1 /, document.querySelector(#root));受控组件受控组件就是受状态控制的组件需要与状态进行相应的绑定 受控组件必须要有一个 onChange 事件否则不能使用 受控组件可以赋予默认值实际上就是设置初始状态官方推荐使用受控组件的写法 可以使用受控组件实现双向绑定。 非受控组件则不是通过与状态进行绑定来实现的而是通过操作 DOM 来实现。除非操作 DOM否则没有办法设置默认值。受控组件实现设置初始状态也就是设置默认值将输入框的 value 值与相应状态进行绑定使用 onChange 事件对状态进行修改从而反映到 value 上class Input extends Component {constructor() {super();this.state {val: // 这个位置用来设置默认值}}handleChange (e) {let val e.target.valuethis.setState({val});}render() {return (div// 让 value 与状态进行绑定通过事件处理修改状态来达到修改值的效果input typetext value{this.state.val} onChange{this.handleChange} /{this.state.val}/div)}
}非受控组件的实现通过 ref 标记一个元素然后可以通过 this.refs.xx 来获取这个元素通过 onChange 事件监听到 value 的变化获取到这个数据然后通过操作 DOM 将数据放到需要的地方class Input extends Component {constructor() {super();this.state {val: }}handleChange (e) {// 这里可以通过 e.target.value 获取let val this.refs.a.value;this.setState({val});}render() {return (divinput typetext onChange{this.handleChange} refa /{this.state.val}/div)}
}实际上上面实现的只是单向绑定如果要实现双向绑定需要使用两个 onChange 事件可以不需要用到状态下面来实现双向绑定class Input extends Component {handleChange (e) {// 这里可以通过 e.target.value 获取if (e.target this.refs.a) {this.refs.b.value e.target.value;} else {this.refs.a.value e.target.value;}}render() {return (div onChange{this.handleChange}input typetext refa /input typetext refb //div)}
}关于前端学习路线的一些建议对你一定有用www.bilibili.com作者前端开发小马哥链接https://juejin.cn/post/6898512934100533261来源掘金