JavaScript中React面向組件編程(上)
前言:
- React組件中默認封裝了很多屬性,有的是提供給開發(fā)者操作的,其中有三個屬性非常重要:state、props、refs。通過這三大核心屬性的使用,我們能夠實現對組件的狀態(tài)進行更新。
一,組件的基本理解和使用
1. 函數組件
<script type="text/babel">
function MyComponent() {
return <h2>我是函數定義的組件(適用于簡單組件的定義)</h2>
}
ReactDOM.render(<MyComponent />, document.getElementById('test'))
</script>
函數組件的渲染過程
1.React解析了組件標簽,找到了對應的組件 2.發(fā)現這個組件是一個函數定義的,隨后調用該函數,生成一個虛擬dom 3.最后將虛擬dom轉化成為真實dom,呈現在頁面中
2. 類式組件
<script type="text/babel">
class MyComponent extends React.Component {
render() {
return <h2>我是類定義的組件適用于復雜數據類型</h2>
}
}
ReactDOM.render(<MyComponent />, document.getElementById('test'))
</script>
類式組件的渲染過程
1.React解析了組件標簽,找到了對應的組件 2.發(fā)現這個組件是一個類定義的,隨后new出來一個實例對象,并通過該實例調用原型上的render方法 3.將render()返回的內容生成一個虛擬dom 4.最后將虛擬dom轉化成為真實dom,呈現在頁面中
3.組件的注意事項
組件名必須首字母大寫 虛擬DOM元素只能有一個根元素 虛擬DOM元素必須有結束標簽
二,組件的三大核心屬性
1.state
state是一個對象,它包含組件的數據狀態(tài),當狀態(tài)變化時,會觸發(fā)視圖的更新。你可以理解它的作用跟Vue中的data對象類似。
<script type="text/babel">
class Weather extends React.Component {
constructor() {
super()
this.state = {
isHot: false,
wind: '微風'
}
this.chang = this.chang.bind(this)
}
render() {
let { isHot, wind } = this.state
return <h2 onClick={this.chang}>今天的天氣很 {isHot ? "炎熱" : "涼爽"},{wind}</h2>
}hang() {
console.log(this)
this.setState({
isHot: !this.state.isHot
})
}
}
ReactDOM.render(<Weather />, document.getElementById('test'))
</script>
1. 注意事項
1.組件中render方法中的this為組件實例對象 2.組件自定義的方法中this為undefined,如何解決? 1.強制綁定this: 通過函數對象的bind() 2.箭頭函數 3.狀態(tài)數據,不能直接修改或更
2.簡寫方式
<script type="text/babel">
class Weather extends React.Component {
state = {
isHot: false,
wind: '微風'
}
render() {
let { isHot, wind } = this.state
return <h2 onClick={this.chang}>今天的天氣很 {isHot ? "炎熱" : "涼爽"},{wind}</h2>
}
chang = ()=>{
this.setState({
isHot: !this.state.isHot//這里的修改是一種合并,對比屬性的變化,如果有賦新值,沒有則跳過
})
}
}
ReactDOM.render(<Weather />, document.getElementById('test'))
let a = new Weather()
</script>
設置狀態(tài):setState
setState(object nextState[, function callback])
不能在組件內部通過this.state修改狀態(tài),因為該狀態(tài)會在調用 setState() 后被替換。
setState() 并不會立即改變 this.state,而是創(chuàng)建一個即將處理的 state。setState() 并不一定是同步的,為了提升性能 React 會批量執(zhí)行 state 和 DOM 渲染。
setState() 總是會觸發(fā)一次組件重繪,除非在 shouldComponentUpdate() 中實現了一些條件渲染邏輯。
2.props
React中組件通過 props 屬性接收外部傳入的數據,這點 Vue 跟 React 是一致的- react 中說的單向數據流值說的就是 props,根據這一特點它還有一個作用:
組件之間的通信。 - props 本身是
不可變的,但是有一種情形它貌似可變,即是將父組件的 state作為子組件的 props,當父組件的 state 改變,子組件的 props 也跟著改變,其實它仍舊遵循了這一定律:props 是不可更改的。
<script type="text/babel">
class MyComponent extends React.Component {
render() {
return (
<ul>
<li>{this.props.name}</li>
<li>{this.props.age}</li>
</ul>
);
}
}
ReactDOM.render(
<MyComponent name="Bob" age="18" />,
document.getElementById("test")
);
</script>
props的特點:
- 每個組件對象都會有props(properties的簡寫)屬性
- 組件標簽的所有屬性都保存在props中
- 內部讀取某個屬性值:this.props.propertyName
- 作用:通過標簽屬性從組件外 向組件內傳遞數據(只讀 read only)
- 對props中的屬性值進行類型限制和必要性限制
對props進行限制
- 引入 prop-type 庫,這就是專門用于限制 props 屬性的一個庫
- 導入 prop-type 庫,到當前頁面
- 根據 Person.propTypes = {} 進行限制
class MyComponent extends React.Component {
render() {
return (
<ul>
<li>{this.props.name}</li>
<li>{this.props.age}</li>
</ul>
);
}
}
// 校驗類型
MyComponent.propTypes = {
name: PropTypes.string, // 這里的 PropTypes 變量是全局掛載的
age: PropTypes.number,
};
ReactDOM.render(
<MyComponent name="Bob" age={18} />,
document.getElementById("test")
);
props的簡寫
<script type="text/babel">
class Weather extends React.Component {
constructor(props) {//是否接受,取決于是否使用外部數據
super(props)//只能上面接受了props,super()就去傳遞,否則后續(xù)的使用,可能就會出現問題
}
static propTypes = {
name: PropTypes.string.isRequired,//限制name為字符串類型,必填
// age: PropTypes.number,
sex: PropTypes.string,
speak: PropTypes.func
}
static defaultProps = {
sex: '男',
}
render() {
let { name, age, sex } = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性別:{sex}</li>
<li>年齡:{age + 1}</li>
</ul>
)
}
}
ReactDOM.render(<Weather name="tom" age={26} sex="女" />, document.getElementById('test'))
</script>
函數組件使用props
<script type="text/babel">
// 函數組件
function MyComponent(props) {
return (
<ul>
<li>{props.name}</li>
<li>{props.age}</li>
</ul>
);
}
// 校驗類型
MyComponent.propTypes = {
name: PropTypes.string,
age: PropTypes.number,
};
ReactDOM.render(
<MyComponent name="Bob" age={18} />,document.getElementById("test")
);
</script>
3.ref
- React 中的 Refs 可以讓我們訪問 DOM 節(jié)點,它有三種使用方式:字符串方式,回調函數式,createRef。
- 在 React 中 Refs 提供了一種方式,允許用戶訪問DOM 節(jié)點或者在render方法中創(chuàng)建的React元素。
- 在 React單項數據流中,props是父子組件交互的唯一方式。要修改一個子組件,需要通過的新的props來重新渲染。
但是在某些情況下,需要在數據流之外強制修改子組件。被修改的子組件可能是一個React組件實例,也可能是一個DOM元素。對于這兩種情況,React 都通過 Refs的使用提供了具體的解決方案。
回調函數方式
<script type="text/babel">
class MyComponent extends React.Component {
handleAlert = () => {
// 直接從組件實例上獲取 myInput
console.log(this.myInput); // <input type="text">
alert(this.myInput.value);
};
render() {
return (
<div>
{/* ref 直接定義成一個回調函數,參數就是節(jié)點本身,將它賦值給組件的一個 myInput 屬性 */}
<input ref={(ele) => (this.myInput = ele)} type="text" />
<button onClick={this.handleAlert}>alert</button>
</div>
);
}
}
ReactDOM.render(<MyComponent />, document.getElementById("test"));
</script>
React官方提示:
如果 ref 回調函數是以內聯函數的方式定義的,在更新過程中它會被執(zhí)行兩次,第一次傳入參數 null,然后第二次會傳入參數 DOM 元素。這是因為在每次渲染時會創(chuàng)建一個新的函數實例,所以 React 清空舊的 ref 并且設置新的。通過將 ref 的回調函數定義成 class 的綁定函數的方式可以避免上述問題,但是大多數情況下它是無關緊要的。
createRef -官方推薦使用
<script type="text/babel">
class MyComponent extends React.Component {
// 創(chuàng)建 ref
myInput = React.createRef();
handleAlert = () => {
console.log(this.myInput.current); // 這里需要注意,元素是在 current 屬性上
alert(this.myInput.current.value);
};
render() {
return (
<div>
{/* 將創(chuàng)建好的 ref 附加到元素上 */}
<input ref={this.myInput} type="text" />
<button onClick={this.handleAlert}>alert</button>
</div>
);
}
}
ReactDOM.render(<MyComponent />, document.getElementById("test"));
</script>
上面就是使用 React.createRef() 方法創(chuàng)建 ref 的方式,特別需要注意的是,創(chuàng)建出來的 ref 的值是一個對象,我們需要的 DOM 元素是放在對象的 current 屬性上,如上面的 this.myInput.current。
總結
以上就是React面向組件編程中的一部分。希望本篇文章能夠幫助到你!
到此這篇關于JavaScript中React面向組件編程的文章就介紹到這了,更多相關React面向組件編程內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
react native基于FlatList下拉刷新上拉加載實現代碼示例
這篇文章主要介紹了react native基于FlatList下拉刷新上拉加載實現代碼示例2018-09-09
react-router-dom入門使用教程(路由的模糊匹配與嚴格匹配)
這篇文章主要介紹了react-router-dom入門使用教程,主要介紹路由的模糊匹配與嚴格匹配,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-08-08

