html, js, css
等)对于组件化,如果一个应用是用多组件的方式进行综合开发的, 那么这个应用就是一个组件化应用。
对于模块,多个组件形成模块, 或者是一个提供特定功能的 js
文件, 主要特点在于耦合性低, 可移植性高, 执行效率好。
对于模块化,如果一个应用都是用模块的形式来构建的,那么这个应用就是模块化应用。
对于 React
中组件创建方式,有构造函数创建组件和 class
关键字创建组件这两种。
对于构造函数创建组件,如下所示:
props
来接收;return
一个合法的 JSX
创建的虚拟 DOM
; <script type="text/babel">
function Name (props) {
return <p>{
props.name}</p>
}
function Gender (props) {
return <p>{
props.gender}</p>
}
function Likes (props) {
return <p>{
props.likes}</p>
}
function Hello () {
return (
<div>
<Name name="张三"/>
<Gender gender="男"/>
<Likes likes={
['react', 'vue']}/>
</div>
)
}
ReactDOM.render(<Hello/>, document.getElementById('app'))
</script>
class
关键字创建组件,代码如下所示: <script type="text/babel">
class Hello extends React.Component {
render () {
return (
<div>
<p>{
props.name} --- {
props.gender} --- {
props.likes}</p>
</div>
)
}
}
ReactDOM.render(
<Hello name="张三" gender="男" likes={
['react', 'vue']}/>,
document.getElementById('app')
)
</script>
class
关键字创建组件的区别,如下所示:class
关键字创建的组件叫:有状态组件;state
(状态)属性;state
,如下所示:React
把组件看成是一个状态机(State Machines)
, 通过状态(State)
去操作状态机;UI
,让用户界面和数据保持一致;React
中,只需更新组件的 state
,然后根据新的 state
重新渲染用户界(不要操作 DOM
)state
的使用方式,代码如下所示: <script type="text/babel">
class Hello extends React.Component {
constructor (props) {
super(props)
this.state = {
name: '张三',
gender: "男",
age: 24
}
}
render () {
const {
name, gender, age} = this.state
return (
<div>
<p>{
props.name} --- {
props.gender} --- {
props.age}</p>
<button onClick={
() => this.updateClick()}>换一个</button>
</div>
)
}
updateClick () {
this.setState({
name: '李四',
gender: "男",
age: 26
})
}
}
ReactDOM.render(
<Hello/>,
document.getElementById('app')
)
</script>
props
和 state
的使用场景?props
的使用细节? <script type="text/babel">
class Person extends React.Component {
constructor (props) {
super(props)
// 初始化state
this.state = {
age: 24,
friends: []
}
}
// 设置props属性的默认值
static defaultProps = {
name: '张三',
gender: '男'
}
// 设置props属性的类型
static propTypes = {
name: PropTypes.string.required,
gender: PropTypes.string.isRequired
}
render () {
const {
name, gender} = this.props
const {
age, friends} = this.state
return (
<div>
<p>姓名:{
name},性别:{
gender}</p>
<p>年龄:{
age}</p>
<p>我的朋友:</p>
<ul>
{
friends.map((friend, index) => (
<li key={
index}>{
friend}</li>
))
}
</ul>
<button onClick={
() => this.addYear()}>加一</button>
</div>
)
}
addYear () {
// 增加
let tempArr = this.state.friends
tempArr.push('朋友'+Math.floor(Math.random()*100))
// 更新状态
this.setState({
age: this.state.age+1,
friends: tempArr
})
}
}
ReactDOM.render(
<Person />,
document.getElementById('app')
)
</script>
props
一般用于接收外部传入的数据; 而 state
则用于记录组件内部数据, 而且是需要经常改变的数据;state
是组件内部的状态(数据),不能够直接修改,必须要通过 setState
来改变值的状态,从而达到更新组件内部数据的作用;props
更多是组件间传递数据的一种方式,props
同样也可以传递 state
。由于 React
的数据流是自上而下的,所以是从父组件向子组件进行传递;另外组件内部的 this.props
属性是只读的不可修改;对于 ref
,Refs
提供了一种方式,用于访问在 render
方法中创建的 DOM
节点或 React
元素。
对于 ref
的使用场景,如下所示:
DOM
库;注意,官方提示, 如果可以通过声明式实现,则尽量避免使用 refs
。话外音: React
无法控制局面的时候,就需要直接操作 Refs
了。
具体实现,代码如下所示:
<script type="text/babel">
class CustomTextInput extends React.Component {
constructor (props) {
super(props)
// 绑定ref
this.myInput = React.createRef()
this.myBtn = React.createRef()
}
render () {
return (
<div>
<input ref={
this.myInput} type="text" placeholder="请输入内容" />
<input ref={
this.myBtn} type="button" value="获取焦点" onClick={
() => this.focusTextInput()}/>
</div>
)
}
focusTextInput () {
// 获取焦点
this.myInput.current.focus()
}
}
ReactDOM.render(
<CustomTextInput />,
document.getElementById('app')
)
</script>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
#app{
margin: 50px auto;width: 600px;}
fieldset{
border: 1px solid purple;margin-bottom: 20px;}
fieldset input{
width: 200px;height: 30px;margin: 10px 0;}
table{
width: 600px;border: 2px solid purple;text-align: center;}
thead{
background-color: purple;color: #fff;}
style>
head>
<body>
<div id="app">div>
<script src="../js/react.development.js">script>
<script src="../js/react-dom.development.js">script>
<script src="../js/babel.min.js">script>
<script src="../js/prop-types.js">script>
<script type="text/babel">
class App extends React.Component {
constructor (props) {
super(props)
this.state = {
studentArr: [
{
name: '周杰伦', age: 30, gender: '男', phone: '18899989839'},
{
name: '谢霆锋', age: 40, gender: '男', phone: '18299839890'},
{
name: '刘德华', age: 50, gender: '男', phone: '18998938783'}
]
}
this.delFromArrWithIndex = this.delFromArrWithIndex.bind(this)
}
delFromArrWithIndex (index) {
const {
studentArr } = this.state
studentArr.splice(index, 1)
this.setState({
studentArr
})
}
render () {
return (
<div>
<Add />
<List studentArr={
this.state.studentArr} delFromArr={
this.delFromArrWithIndex}/>
</div>
)
}
}
class Add extends React.Component {
render () {
return (
<div>
<fieldset>
<legend>信息录入系统(React版)</legend>
<div>
<span>姓名: </span>
<input type="text" placeholder="请输入姓名"/>
</div>
<div>
<span>年龄: </span>
<input type="text" placeholder="请输入年龄"/>
</div>
<div>
<span>性别: </span>
<select>
<option value="男">男</option>
<option value="女">女</option>
</select>
</div>
<div>
<span>手机: </span>
<input type="text" placeholder="请输入手机号码"/>
</div>
<button>创建新用户</button>
</fieldset>
</div>
)
}
}
class List extends React.Component {
static propTypes = {
studentArr: PropTypes.array.isRequired,
delFromArr: PropTypes.func.isRequired
}
render () {
const {
studentArr, delFromArr } = this.props
return (
<div>
<table>
<thead>
<tr>
<td>姓名</td>
<td>性别</td>
<td>年龄</td>
<td>手机</td>
<td>删除</td>
</tr>
</thead>
<tbody>
{
studentArr.map((student, index) => (
<tr key={
index}>
<td>{
student.name}</td>
<td>{
student.gender}</td>
<td>{
student.age}</td>
<td>{
student.phone}</td>
<td>
<button onClick={
() => this.delFromArr(index)}>删除</button>
</td>
</tr>
))
}
</tbody>
</table>
</div>
)
}
}
ReactDOM.render(
<App/>, document.getElementById('app')
)
script>
body>
html>
多层组件中, 数据该放在何处?如果只用于一个组件, 则定义在该组件内容; 如果是运用于多个组件, 则定义在它们的父组件中。
多层组件中, 数据传递问题?父组件通过 props
传递数据给子组件, 子组件不能直接修改父组件的数据, 必须是父组件定义修改数据的函数, 传递给子组件然后由子组件调用。
受控方式的实现,代码如下所示:
<script type="text/babel">
class Login extends React.Component {
constructor (props) {
super(props)
this.state = {
userName: '',
userPwd: ''
}
}
render () {
const {
userName, userPwd} = this.state
return (
<form action="" onSubmit={
() => this.login()}>
<div>
<span>用户名:</span>
<input type="text" value={
userName} onChange={
(e) => this.userChange(e)} />
</div>
<div>
<span>密码:</span>
<input type="password" value={
userPwd} onChange={
(e) => this.pwdChange(e)} />
</div>
<input type="submit" value="登录" />
</form>
)
}
userChange (e) {
const userName = e.target.value
this.setState({
userName
})
}
pwdChange (e) {
const userPwd = e.target.value
this.setState({
userPwd
})
}
login () {
const {
userPwd, userName } = this.state
alert(`用户名:${
userName},密码:${
userPwd}`)
return
}
}
ReactDOM.render(
<Login />,
document.getElementById('app')
)
</script>
ref
方式官方不希望过渡使用。