<body>
<div id="test"></div>
<script type="text/babel">
// 创建组件
class Demo extends React.Component {
showDate = () =>{
let {input1} = this.refs
alert(input1.value)
}
showDate2 = () =>{
let {input2} = this.refs
alert(input2.value)
}
render() {
return(
<div>
<input ref="input1" type="text" placeholder="点击按钮提示信息"/>
<button onClick={this.showDate}>点我</button>
<input ref="input2" type="text" onBlur={this.showDate2} placeholder="失去焦点后提示信息"/>
</div>
)
}
}
// 渲染到页面上
ReactDOM.render(<Demo/>, document.getElementById("test"))
</script>
</body>
<body>
<div id="test"></div>
<script type="text/babel">
// 创建组件
class Demo extends React.Component {
showDate = () =>{
let {input1} = this
alert(input1.value)
}
showDate2 = () =>{
let {input2} = this
alert(input2.value)
}
render() {
return(
<div>
<input ref={ c => this.input1 = c } type="text" placeholder="点击按钮提示信息"/>
<button onClick={this.showDate}>点我</button>
<input ref={ c => this.input2 = c } type="text" onBlur={this.showDate2} placeholder="失去焦点后提示信息"/>
</div>
)
}
}
// 渲染到页面上
ReactDOM.render(<Demo/>, document.getElementById("test"))
</script>
</body>
<body>
<div id="test"></div>
<script type="text/babel">
// 创建组件
class Demo extends React.Component {
/*
React.createRef调用后可以返回一个容器,容器可以存储被ref所标识的节点,该容器是“专人专用”的
1.通过onXxx属性指定事件处理函数(注意大小写)
a.React使用的是自定义(合成)事件,而不是使用的原生DOM事件. 为了更好的兼容性
b.React中的事件是通过事件委托方式处理的(委托给组件最外层的元素), 为了的高效
2.通过event.target得到发生事件的DOM元素对象,不要过度使用ref
*/
myRef1 = React.createRef()
myRef2 = React.createRef()
showDate = () =>{
alert(this.myRef1.current.value)
}
showDate2 = () =>{
alert(this.myRef2.current.value)
}
render() {
return(
<div>
<input ref={ this.myRef1 } type="text" placeholder="点击按钮提示信息"/>
<button onClick={this.showDate}>点我</button>
<input ref={ this.myRef2 } type="text" onBlur={this.showDate2} placeholder="失去焦点后提示信息"/>
</div>
)
}
}
// 渲染到页面上
ReactDOM.render(<Demo/>, document.getElementById("test"))
</script>
</body>
React.Children 是顶层API之一,为处理 this.props.children 这个封闭的数据结构提供了有用的工具。
this.props 对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children 属性。它表示组件的所有子节点。
<body>
<div id="test"></div>
<script type="text/babel">
/*
React.Children 是顶层API之一,为处理 this.props.children 这个封闭的数据结构提供了有用的工具。
this.props 对象的属性与组件的属性一一对应,但是有一个例外,就是 this.props.children 属性。它表示组件的所有子节点。
*/
class Child extends React.Component {
render(){
console.log(this)
return <div></div>
}
}
class Demo extends React.Component {
render() {
return(
<div>
<Child>
<h1>今天的天气阴了</h1>
<h1>明天的天气不知道</h1>
</Child>
</div>
)
}
}
ReactDOM.render(<Demo/>, document.getElementById("test"))
</script>
</body>
<body>
<div id="test"></div>
<script type="text/babel">
let message = `
夏天真好
又亮又白
`
class Demo extends React.Component {
render() {
return(
<div dangerouslySetInnerHTML={{
__html:message
}}>
</div>
)
}
}
ReactDOM.render(<Demo/>, document.getElementById("test"))
</script>
</body>
- 只要执行setState(),即使不改变状态数据, 组件也会重新render() ==> 效率低
- 只当前组件重新render(), 就会自动重新render子组件,纵使子组件没有用到父组件的任何数据 ==> 效率低
只有当组件的state或props数据发生改变时才重新render()
Component中的shouldComponentUpdate()总是返回true
办法1:
重写shouldComponentUpdate()方法
比较新旧state或props数据, 如果有变化才返回true, 如果没有返回false
办法2:
使用PureComponent
PureComponent重写了shouldComponentUpdate(), 只有state或props数据有变化才返回true
项目中一般使用PureComponent来优化
<body>
<div id="test"></div>
<script type="text/babel">
// 非受控组件性质, 现用现取, 什么时候用, 什么时候取
// 创建组件
class Demo extends React.Component {
dain = (event) =>{
event.preventDefault(); // 阻止表单提交
let {username,password} = this
alert(`你的用户名是:${username.value}, 你的密码是: ${password.value}`)
}
render() {
return(
<form onSubmit={this.dain}>
用户名: <input ref={c => this.username = c} type="text" name="username"/>
密码: <input ref={c => this.password = c} type="password" name="password"/>
<button>登录</button>
</form>
)
}
}
// 渲染到页面上
ReactDOM.render(<Demo/>, document.getElementById("test"))
</script>
</body>
<body>
<div id="test"></div>
// 类似于vue中的 v-model
<script type="text/babel">
// 创建组件
class Demo extends React.Component {
// 初始化状态
state = {
username:'',
password:''
}
// 保存用户名到状态中
username = (event) =>{
this.setState({username:event.target.value})
}
// 保存密码到状态中
password = (event) =>{
this.setState({password:event.target.value})
}
dain = (event) =>{
event.preventDefault(); // 阻止表单提交
let {username,password} = this.state
alert(`你的用户名是:${username}, 你的密码是: ${password}`)
}
render() {
return(
<form onSubmit={this.dain}>
用户名: <input onChange={this.username} type="text" name="username"/>
密码: <input onChange={this.password} type="text" name="password" name="password"/>
<button>登录</button>
</form>
)
}
}
// 渲染到页面上
ReactDOM.render(<Demo/>, document.getElementById("test"))
</script>
</body>
1)Hook是React 16.8.0版本增加的新特性/新语法
2)可以让你在函数组件中使用 state 以及其他的 React 特性
1). State Hook: React.useState()
2). Effect Hook: React.useEffect()
3). Ref Hook: React.useRef()
1). State Hook让函数组件也可以有state状态, 并进行状态数据的读写操作
2). 语法: const [xxx, setXxx] = React.useState(initValue)
3). useState()说明:
参数: 第一次初始化指定的值在内部作缓存
返回值: 包含2个元素的数组, 第1个为内部当前状态值, 第2个为更新状态值的函数
4). setXxx()2种写法:
setXxx(newValue): 参数为非函数值, 直接指定新的状态值, 内部用其覆盖原来的状态值
setXxx(value => newValue): 参数为函数, 接收原本的状态值, 返回新的状态值, 内部用其覆盖原来的状态值
import React,{Component} from 'react';
function Dome(){
const [count,setCount] = React.useState(0)
// 加的回调
function add(){
// setCount(count+1) // 第一种写法
setCount(count => count+1)
}
return(
<div>
<h1>当前求和为: {count}</h1>
<button onClick={add}>点我</button>
</div>
)
}
export default Dome
1). Effect Hook 可以让你在函数组件中执行副作用操作(用于模拟类组件中的生命周期钩子)
2). React中的副作用操作:
发ajax请求数据获取
设置订阅 / 启动定时器
手动更改真实DOM
3). 语法和说明:
useEffect(() => {
// 在此可以执行任何带副作用操作
return () => { // 在组件卸载前执行
// 在此做一些收尾工作, 比如清除定时器/取消订阅等
}
}, [stateValue]) // 如果指定的是[], 回调函数只会在第一次render()后执行
4). 可以把 useEffect Hook 看做如下三个函数的组合
componentDidMount()
componentDidUpdate()
componentWillUnmount()
import React,{Component} from 'react';
import ReactDOM from 'react-dom';
function Dome(){
const [count,setCount] = React.useState(0)
React.useEffect(()=>{
let timer = setInterval(()=>{
setCount(count => count+1)
},1000)
return ()=>{ // 这里的return就相当于componentWillUnmount()
clearInterval(timer)
}
},[]) // 这里加上一个数组([]),就相当于 componentDidMount()
// 如果你在里面写属性了,他就会监听你写入的属性, 这是就相当于 componentDidUpdate()
// 加的回调
function add(){
// setCount(count+1) // 第一种写法
setCount(count => count+1) // 第二种写法
}
// 卸载组件的回调
function unmount(){
ReactDOM.unmountComponentAtNode(document.getElementById('root'));
}
return(
<div>
<h1>当前求和为: {count}</h1>
<button onClick={add}>点我</button>
<button onClick={unmount}>点击卸载组件</button>
</div>
)
}
export default Dome
1). Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据
2). 语法: const refContainer = useRef()
3). 作用:保存标签对象,功能与React.createRef()一样
import React,{Component} from 'react';
function Dome(){
// Ref Hook可以在函数组件中存储/查找组件内的标签或任意其它数据
// 作用:保存标签对象,功能与React.createRef()一样
const myRef = React.useRef()
// 提示输入的回调
function show(){
alert(myRef.current.value);
}
return(
<div>
<input type="text" ref={myRef}/>
<button onClick={show}>点击提示数据</button>
</div>
)
}
export default Dome
自定义Hooks 函数 和 用Hooks 创建组件很相似,跟我们平时用 JavaScript 写函数几乎一模一样,
可能就是多了些 React Hooks 的特性,自定义 Hooks 函数偏向于功能,而组件偏向于界面和业务逻辑。
import React,{useState,useEffect,useCallback} from 'react'
function useWinSize(){
const [size,setSize] = useState({ // 先用useState设置size状态
width:document.documentElement.clientWidth,
height:document.documentElement.clientHeight
})
// 编写一个每次修改状态的方法 onResize
const onResize = useCallback( // 使用callback,目的是为了缓存方法(useMemo是为了缓存变量)
() => {
setSize({
width:document.documentElement.clientWidth,
height:document.documentElement.clientHeight
})
},
[],
)
// 在第一次进入方法时使用useEffect 来注册 resize 监听事件
useEffect(() => {
window.addEventListener('resize:',onResize)
return () => {
// 为了防止一直监听,在方法移除时,使用return 的方式移除监听
window.removeEventListener('resize:',onResize)
}
}, [])
// 最后返回size变量
return size;
}
// 编写组件并使用自定义函数
function HWinsize(){
const size=useWinSize()
return(
<div>
页面size:{size.width} x {size.height}
</div>
)
}
export default HWinsize;
ref,dangerouslySetInnerHTML和Child,PureComponent,非受控组件和受控组件,Hooks
, 其中的注意点作者已经在上面标明了, 最后我想说知识从来不是看看就会的,要多实践,多敲代码.