摘要:我們可以使用函數構造函數將我們的組件轉換為狀態什么是函數構造函數在中,函數是一個在創建對象時運行的函數。我們將使用構造函數方法在對象創建時正確運行對象時設置實例變量。每當一個有一個屬性被設置時,它會在該字段改變的每個時間調用函數。
本文轉載自:眾成翻譯
譯者:iOSDevLog
鏈接:http://www.zcfy.cc/article/3823
原文:https://www.fullstackreact.com/30-days-of-react/day-10/
今天,我們將介紹如何添加交互性到我們的應用,使其具有吸引力和交互性。
通過這一點,我們構建了少數幾個組件,而沒有添加用戶交互。 今天我們將要改變它。
用戶交互瀏覽器是事件驅動的應用程序。 用戶在瀏覽器中進行的一切都會觸發一個事件,從點擊按鈕,甚至只是移動鼠標。 在簡單的JavaScript中,我們可以監聽這些事件并附加一個JavaScript函數與它們進行交互。
例如,我們可以使用JS附加一個函數到mousemove瀏覽器事件:
export const go = () => { const ele = document.getElementById("mousemove"); ele.innerHTML = "Move your mouse to see the demo"; ele.addEventListener("mousemove", function(evt) { const { screenX, screenY } = evt; ele.innerHTML = "Mouse is at: X: " + screenX + ", Y: " + screenY + ""; }) }
這導致以下行為:
將鼠標移到該文本上
然而,在React中,我們不必在原始JavaScript中與瀏覽器的事件循環進行交互,因為React為我們使用props處理事件提供了一種方法。
例如,要從React上面的(相當不起眼的)演示中收聽mousemove 事件,我們將設置onMouseMove (請注意事件名稱是駝峰命名的)。
console.log(evt)}> Move the mouse
React提供了很多props ,我們可以設置監聽不同的瀏覽器事件,例如點擊,觸摸,拖動,滾動,選擇事件等等(參見事件文檔列出所有這些)。
要看看其中的一些在行動中,以下是一些小的演示,一些props ,我們可以傳遞我們的元素。 列表中的每個文本元素設置其列出的屬性。 嘗試使用列表查看事件在元素中的調用和處理方式。
我們將在我們的應用中使用 onClick 屬性相當多,所以熟悉它是一個好主意。 在我們的活動列表標題中,我們有一個搜索圖標,我們還沒有與顯示一個搜索框關聯起來。
我們_想要_的交互是在用戶點擊搜索圖標時顯示搜索。 回想一下,我們的Header組件是這樣實現的:
class Header extends React.Component { constructor(props) { super(props); this.state = { searchVisible: false } } // toggle visibility when run on the state showSearch() { this.setState({ searchVisible: !this.state.searchVisible }) } render() { // Classes to add to the element let searchInputClasses = ["searchInput"]; // Update the class array if the state is visible if (this.state.searchVisible) { searchInputClasses.push("active"); } return () } }{this.props.title} {/* Adding an onClick handler to call the showSearch button */}
當用戶點擊 元素時,我們需要運行一個函數來更新組件的狀態,以便searchInputClasses對象更新。 使用onClick處理程序,這很簡單。
我們讓這個組件有狀態(它需要跟蹤搜索字段是否應該顯示)。 我們可以使用constructor() 函數(構造函數)將我們的組件轉換為狀態:
class Header extends React.Component { constructor(props) { super(props); this.state = { searchVisible: false } } // ... }
什么是constructor函數(構造函數)?在JavaScript中,constructor 函數是一個在創建對象時運行的函數。它返回對創建實例的prototype的Object函數的引用。
在純英文中,構造函數是JavaScript運行時創建新對象時運行的函數。我們將使用構造函數方法在對象創建時正確運行對象時設置實例變量。
當使用ES6類語法創建對象時,我們必須在任何其他方法之前調用super() 方法。調用super() 函數調用父類的 constructor() 函數。我們將使用_相同參數_調用它,因為我們類的 constructor() 函數被調用。
當用戶點擊按鈕時,我們將要更新狀態來表示searchVisible 標志被更新。由于我們希望用戶能夠第二次點擊搜索圖標后關閉/隱藏 字段,所以我們將_切換_該狀態,而不是將其設置為true。
我們創建這個方法來綁定我們的點擊事件:
class Header extends React.Component { // ... showSearch() { this.setState({ searchVisible: !this.state.searchVisible }) } // ... }
最后,我們可以在icon元素上附加一個點擊處理程序(使用onClick 屬性)來調用我們新的 showSearch() 方法。 我們的 Header組件的整個更新的源代碼如下所示:
class Header extends React.Component { constructor(props) { super(props); this.state = { searchVisible: false } } // toggle visibility when run on the state showSearch() { this.setState({ searchVisible: !this.state.searchVisible }) } render() { // Classes to add to the element let searchInputClasses = ["searchInput"]; // Update the class array if the state is visible if (this.state.searchVisible) { searchInputClasses.push("active"); } return ({this.props.title} {/* Adding an onClick handler to call the showSearch button */}) } }
嘗試點擊搜索圖標并觀看輸入字段出現并消失(動畫效果由CSS動畫處理)。
輸入事件無論何時在React中構建表單,我們將使用React提供的輸入事件。最值得注意的是,我們最常使用 onSubmit() 和onChange()屬性。
我們更新我們的搜索框演示,以便在更新時捕獲搜索字段內的文本。每當一個 有一個 onChange()屬性被設置時,它會在該字段_改變_的每個時間調用函數。當我們點擊它并開始輸入時,該函數將被調用。
使用這個屬性,我們可以捕捉到我們這個字段的價值。
讓我們創建一個新的子組件來包含一個 元素而不是更新我們的
我們創建一個我們稱之為SearchForm的新組件。這個新組件是一個有狀態的組件,因為我們需要保持搜索輸入的值(跟蹤它的變化):
class SearchForm extends React.Component { // ... constructor(props) { super(props); this.state = { searchText: "" } } // ... }
現在,我們已經在
class SearchForm extends React.Component { // ... render() { const { searchVisible } = this.state; let searchClasses = ["searchInput"] if (searchVisible) { searchClasses.push("active") } return (); } }
請注意,我們在我們的 字段上丟失了樣式。 由于我們不再在我們的新 組件中具有searchVisible狀態,所以我們不能再使用它來對其進行風格化了。 _無論如何_,我們可以從我們的Header組件傳遞一個支持,該組件告訴SearchForm將輸入渲染為可見。
我們定義searchVisible 屬性(當然使用React.PropTypes),并更新render函數以使用新的prop值來顯示(或隱藏)搜索。 我們還將為字段的可見性設置一個默認值為false(因為我們的Header顯示/隱藏它很好):
class SearchForm extends React.Component { static propTypes = { onSubmit: React.PropTypes.func.isRequired, searchVisible: React.PropTypes.bool } // ... }
現在我們在 元素上有我們的樣式,讓我們添加用戶在搜索框中鍵入的功能,我們將要捕獲搜索字段的值。 我們可以通過將onChange參數附加到 元素上來實現這個工作流,并在每次更改 元素時傳遞一個函數來調用它。
class SearchForm extends React.Component { // ... updateSearchInput(e) { const val = e.target.value; this.setState({ searchText: val }); } // ... render() { const { searchVisible } = this.state; let searchClasses = ["searchInput"] if (searchVisible) { searchClasses.push("active") } return (); } }
當我們鍵入字段時,將會調用updateSearchInput() 函數。 我們將通過更新狀態來跟蹤表單的值。 在updateSearchInput() 函數中,我們可以直接調用this.setState() 來更新組件的狀態。
該值在event對象的目標上保存為`event.target.value"。
class SearchForm extends React.Component { // ... updateSearchInput(e) { const val = e.target.value; this.setState({ searchText: val }); } // ... }
控制與不受控制我們正在創建所謂的不受控制的組件,因為我們沒有設置 元素的值。 我們現在不能對輸入的文本值提供任何驗證或后處理。
如果我們要驗證字段或操作 組件的值,我們將必須創建一個所謂的控件組件,這真的只是意味著我們使用value"傳遞一個值 屬性。 受控組件版本的render()` 函數將如下所示:
class SearchForm extends React.Component { render() { return ( ); } }
到目前為止,我們無法真正提交表單,所以我們的用戶無法真正搜索。 我們來改變一下 我們需要將component包含在一個DOM元素中,這樣我們的用戶可以按回車鍵提交表單。 我們可以使用 元素上的onSubmit支持來捕獲表單提交。
我們來更新render()函數來反映這個變化。
class SearchForm extends React.Component { // ... submitForm(e) { e.preventDefault(); const {searchText} = this.state; this.props.onSubmit(searchText); } // ... render() { const { searchVisible } = this.props; let searchClasses = ["searchInput"] if (searchVisible) { searchClasses.push("active") } return (); } }
我們立即在submitForm()函數上調用event.preventDefault()。這將阻止瀏覽器冒泡,從而使整個頁面的默認行為重新加載(瀏覽器提交表單時的默認功能)。
現在當我們鍵入 字段并按回車鍵,submitForm() 函數被調用的事件對象。
那么好的,我們可以提交表單和內容,但是什么時候我們實際上進行搜索?為了演示目的,我們將把搜索文本傳遞給父子組件鏈,以便 Header 可以決定搜索_什么_。
SearchForm 組件當然不知道它正在搜索什么,所以我們必須把責任傳遞給鏈。我們將會使用這種回調策略。
為了將搜索功能傳遞給鏈,我們的“SearchForm”將需要接受在提交表單時調用的函數。我們來定義一個我們稱之為 SearchForm 的屬性,我們可以傳遞給我們的SearchForm 組件。作為好的開發人員,我們還會為這個onSubmit函數添加默認的prop值和propType。因為我們想要確定onSubmit() 是被定義的,所以我們將把onSubmit的prop設置成一個必需的參數:
class SearchForm extends React.Component { static propTypes = { onSubmit: React.PropTypes.func.isRequired, searchVisible: React.PropTypes.bool } // ... static defaultProps = { onSubmit: () => {}, searchVisible: false } // ... }
當表單提交時,我們可以直接從props調用這個函數。 由于我們在跟蹤我們狀態下的搜索文本,所以我們可以在該狀態下使用searchText值調用該函數,因此onSubmit() 函數只能獲取值并且不需要處理事件。
class SearchForm extends React.Component { // ... submitForm(event) { // prevent the form from reloading the entire page event.preventDefault(); // call the callback with the search value this.props.onSubmit(this.state.searchText); } }
現在,當用戶按下enter時,我們可以通過我們的Header 組件來調用props 中傳遞的onSubmit() 函數。
我們可以在我們的 Header 組件中使用這個 SearchForm 組件,并傳遞我們定義的兩個屬性(searchVisible 和onSubmit):
import React from "react"; import SearchForm from "./SearchFormWithSubmit" class Header extends React.Component { constructor(props) { super(props); this.state = { searchVisible: false } } // toggle visibility when run on the state showSearch() { this.setState({ searchVisible: !this.state.searchVisible }) } render() { // Classes to add to the element let searchInputClasses = ["searchInput"]; // Update the class array if the state is visible if (this.state.searchVisible) { searchInputClasses.push("active"); } return () } } export default Header{this.props.title}{/* Adding an onClick handler to call the showSearch button */}
現在我們有一個搜索表單組件,可以在我們的應用中使用和重用。 當然,我們還沒有搜索任何東西。 我們來解決這個問題,實現搜索。
[](#implementing-search)實現搜索要在我們的組件中實現搜索,我們希望將搜索責任從我們的 Header 組件傳遞到容器組件,我們稱之為 Panel。
首先,讓我們實現一個從 Panel 容器到Header 組件的子組件中將回調傳遞給父組件的模式。
在Header 組件上,我們來更新一個屬性的propTypes ,我們將它定義為onSearch屬性:
class Header extends React.Component { // ... } Header.propTypes = { onSearch: React.PropTypes.func }
在Header 組件的"submitForm()"函數里面,調用這個onSearch() 屬性,我們將傳入它:
class Header extends React.Component { // ... submitForm(val) { this.props.onSearch(val); } // ... } Header.propTypes = { onSearch: React.PropTypes.func }
請注意,我們的虛擬樹如下所示:
當
更新時,它會傳遞它的意識,搜索輸入的變化到它的父組件 ,當它將向上傳遞到 組件。 這種方法在React應用中是_very common_,并為我們的組件提供了一套很好的功能隔離。
回到我們在第7天構建的Panel 組件中,我們將把一個函數作為Header 的onSearch() 屬性傳遞給Header。 我們在這里說的是,當提交搜索表單時,我們希望搜索表單回調到頭部組件,然后調用 Panel 組件來處理搜索。
由于Header 組件不能控制內容列表,所以Panel組件可以像我們在這里定義一樣,我們_必須_將職責更多地傳遞給他們。
無論如何,我們的Panel 組件本質上是我們之前使用的Content組件的副本:
class Panel extends React.Component { constructor(props) { super(props); this.state = { loading: false, // <~ set loading to false activities: data, filtered: data, } } componentDidMount() {this.updateData();} componentWillReceiveProps(nextProps) { // Check to see if the requestRefresh prop has changed if (nextProps.requestRefresh !== this.props.requestRefresh) { this.setState({loading: true}, this.updateData); } } handleSearch = txt => { if (txt === "") { this.setState({ filtered: this.state.activities }) } else { const { activities } = this.state const filtered = activities.filter(a => a.actor && a.actor.login.match(txt)) this.setState({ filtered }) } } // Call out to github and refresh directory updateData() { this.setState({ loading: false, activities: data }, this.props.onComponentRefresh); } render() { const {loading, filtered} = this.state; return () } } {/* Show loading message if loading */} {loading &&Loading} {/* Timeline item */} {filtered.map((activity) => ())}
我們更新我們的狀態以包括一個searchFilter字符串,這將只是搜索值:
class Panel extends React.Component { constructor(props) { super(props); this.state = { loading: false, searchFilter: "", activities: [] } } }
為了實際處理搜索,我們需要將onSearch() 函數傳遞給我們的Header 組件。 我們在我們的Panel組件中定義一個onSearch() 函數,并將其傳遞給render() 函數中的Header 屬性。
class Panel extends React.Component { // ... // after the content has refreshed, we want to // reset the loading variable onComponentRefresh() {this.setState({loading: false});} handleSearch(val) { // handle search here } render() { const {loading} = this.state; return () } }
我們在這里所做的就是添加一個handleSearch() 函數并將其傳遞給標題。 現在當用戶鍵入搜索框時,我們的Panel組件上的handleSearch() 函數將被調用。
為了_實現_搜索,我們需要跟蹤這個字符串,并更新我們的updateData() "函數來考慮搜索過濾。 首先讓我們把searchFilter 設置為狀態。 我們也可以強制內容通過將加載設置為true來重新加載數據,因此我們可以在一個步驟中執行此操作:
class Panel extends React.Component { // ... handleSearch(val) { this.setState({ searchFilter: val, loading: true }); } // ... }
最后,我們更新我們的updateData()函數來考慮_搜索_帳戶。
class SearchableContent extends React.Component { // ... this.setState({loading: true}, this.updateData); // ... }
雖然這可能看起來很復雜,但它實際上幾乎與我們現有的updateData() 函數完全相同,除了我們更新了我們的fetch()結果以在json集合上調用filter() 方法。
所有的collection.filter() 函數都是運行著每個元素傳遞的函數,并且過濾_掉_返回偽造值的值,保留返回真值的值。我們的搜索功能只是在Github活動的 actor.login (Github用戶)上查找匹配,以查看它是否正確匹配searchFilter 值。
隨著updateData() 功能的更新,我們的搜索完整了。
嘗試搜索auser。
現在我們有一個3層應用組件來處理嵌套子組件的搜索。我們通過這個post從初級階段跳到了中級階段。靠著自己。這是一些重大的材料。確保你明白這一點,因為我們會經常使用我們今天介紹的這些概念。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/84668.html
摘要:今天我們將討論創建組件的最終方案,即無狀態函數的純組件。今天我們正在研究一種處理提出的復雜數據的方法,稱為體系結構。第天部署介紹今天,我們將探討部署我們的應用所涉及的不同部分,以便外界可以使用我們的應用。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3758原文:https://www.fullstackreact.com/3...
摘要:我們的應用由一個單一的元素組成。讓我們通過構建我們的第一個組件來開始接觸這個力量。我們將把組件寫成類。讓我們來看一個我們要調用的組件。然而,什么都不會在屏幕上呈現。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3799原文:https://www.fullstackreact.com/30-days-of-react/day-...
摘要:本文轉載自眾成翻譯譯者鏈接原文太棒了,我們已經構建了第一個組件。天前一章節,我們開始構建我們的第一個組件。內容部分內有個不同的項目組件。決定劃分組件的深度比科學更顯得藝術。子組件當組件嵌套在另一個組件中時,它被稱為子組件。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3817原文:https://www.fullstackre...
摘要:本文轉載自眾成翻譯譯者鏈接原文今天,我們從一開始就開始。讓我們看看是什么,是什么讓運轉起來。什么是是一個用于構建用戶界面的庫。它是應用程序的視圖層。所有應用程序的核心是組件。組件是可組合的。虛擬完全存在于內存中,并且是網絡瀏覽器的的表示。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3765原文:https://www.ful...
摘要:我們將為組件賦值,并使用選擇器來定位頁面上的元素,讓瀏覽器處理樣式。的工作方式是將因此命名父樣式作為子樣式的樣式。這通常是錯誤的原因,因為類通常具有通用名稱,并且易于覆蓋非特定類的類樣式。反之,我們的樣式名稱需要使用駝峰命名方式。 本文轉載自:眾成翻譯譯者:iOSDevLog鏈接:http://www.zcfy.cc/article/3820原文:https://www.fullsta...
閱讀 685·2021-11-25 09:43
閱讀 2953·2021-11-24 10:20
閱讀 1002·2021-10-27 14:18
閱讀 1076·2021-09-08 09:36
閱讀 3382·2021-07-29 14:49
閱讀 1784·2019-08-30 14:07
閱讀 2937·2019-08-29 16:52
閱讀 3049·2019-08-29 13:12