react 組件引用組件
A few months ago I posted to Twitter what I thought was a simple question:
幾個月前,我在Twitter上發布了一個我認為簡單的問題:
What surprised me wasn’t the joint confusion around this question, but rather the amount of inaccurate responses I received.
讓我感到驚訝的不是關于這個問題的共同困惑,而是我收到的不準確的答復。
Instances / Instantiation
實例/實例化
Instances / Instantiation Rendering
實例/實例化 渲染
Instances / Instantiation RenderingEvaluation
實例/實例化 渲染 評估
Instances / Instantiation RenderingEvaluationInvocation
實例/實例化 渲染 評估 調用
Instances / Instantiation RenderingEvaluationInvocation“Using it :)”
實例/實例化 渲染 評估 調用 “使用它:)”
The primary reason for the confusion is that there’s an often un-talked about abstraction layer between JSX and what’s actually going on in React land. In order to answer this question, we need to take a deep dive into that abstraction.
造成混淆的主要原因是,在JSX與React領域中實際發生的事情之間經常沒有談論抽象層。 為了回答這個問題,我們需要深入研究該抽象。
Let’s start by looking at the absolute fundamentals of React.
讓我們從了解React的絕對基礎開始。
React到底是什么? (What exactly is React?)
React is a library for building user interfaces. No matter how complex React or the React ecosystem seem to be, this is React at its core — building UIs. With this in mind, we arrive at our first definition, an Element.
React是用于構建用戶界面的庫。 無論React或React生態系統看起來多么復雜,這都是React的核心-構建UI。 考慮到這一點,我們得出了第一個定義, Element 。
Simply put, a React element describes what you want to see on the screen.
簡而言之, React元素描述了您想要在屏幕上看到的內容 。
Not so simply put, a React element is an object representation of a DOM node.
簡而言之, React元素是DOM節點的對象表示 。
Notice that I used the word describe. It’s important to note that a React element isn’t actually the thing you’ll see on your screen, instead, it’s just an object representation of it. There are a few reasons for this:
注意,我使用了describe這個詞。 重要的是要注意,React元素實際上并不是您將在屏幕上看到的東西,而是它的對象表示。 這有幾個原因:
- JavaScript objects are lightweight. React can create and destroy these elements without too much overhead. JavaScript對象是輕量級的。 React可以創建和銷毀這些元素,而無需太多開銷。
- React is able to analyze the object, then analyze the actual DOM, and then update the actual DOM only where a change occurred. This has some performance upsides to it. React能夠分析對象,然后分析實際DOM,然后僅在發生更改的地方更新實際DOM。 這具有一些性能優勢。
In order to create our object representation of a DOM node (aka React element), we can use React’s createElement method.
為了創建我們的DOM節點(又名React元素)的對象表示,我們可以使用React的createElement方法。
const element = React.createElement( 'div', {id: 'login-btn'}, 'Login')
createElement
takes in three arguments:
createElement
接受三個參數:
- a tag name string (div, span, etc.) 標簽名稱字符串(div,span等)
- any attributes you want the element to have 您希望元素具有的任何屬性
- contents or the children of the element — in this case the text “Login”. 元素的內容或子元素-在這種情況下為“登錄”文本。
The createElement
invocation above is going to return an object with this shape:
上面的createElement
調用將返回具有以下形狀的對象:
{ type: 'div', props: { children: 'Login', id: 'login-btn' } }
And when it’s rendered to the DOM (using ReactDOM.render), we’ll have a new DOM node that looks like this:
當將其渲染到DOM時(使用ReactDOM.render),我們將擁有一個新的DOM節點,如下所示:
<div id='login-btn'>Login</div>
So far, so good. What’s interesting about learning React is that typically the first thing you’re taught is components. “Components are the building blocks of React.”
到目前為止,一切都很好。 學習React的有趣之處在于,通常您首先要學習的是組件。 “組件是React的基石。”
Notice, however, that we started this post with elements. The reason for this is because once you understand elements, understanding components is a smooth transition.
但是請注意,我們是從元素開始的。 這樣做的原因是,一旦您理解了元素,理解組件就是一個平穩的過渡。
A component is a function or a Class which optionally accepts input and returns a React element.
組件是可以選擇接受輸入并返回React元素的函數或類。
function Button ({ onLogin }) { return React.createElement( 'div', {id: 'login-btn', onClick: onLogin}, 'Login' )}
By definition, we have a Button component which accepts an onLogin input and returns a React element. One thing to note is that our Button component receives an onLogin method as its prop. To pass that along to our object representation of the DOM, we pass it along as the second argument to createElement, just as we did our id attribute.
根據定義,我們有一個Button組件,它接受一個onLogin輸入并返回一個React元素。 需要注意的一件事是,我們的Button組件接收一個onLogin方法作為其支持。 要將其傳遞給我們的DOM對象表示,我們將其作為createElement的第二個參數傳遞,就像我們的id屬性一樣。
Let’s go deeper.
讓我們更深入。
Up until this point we’ve only covered creating React elements with the “type” property of native HTML elements (“span”, “div”, etc), but you can also pass in other React components to the first argument of createElement.
到目前為止,我們僅介紹了使用本機HTML元素(“ span”,“ div”等)的“ type”屬性創建React元素的方法,但是您也可以將其他React組件傳遞給createElement的第一個參數。
const element = React.createElement( User, {name: 'Tyler McGinnis'}, null )
However, unlike with an HTML tag name, if React sees a class or a function as the first argument, it will then check to see what element it renders, given the corresponding props. React will continue to do this until there are no more createElement invocations which have a class or a function as their first argument. Let’s take a look at this in action.
但是,與HTML標簽名稱不同的是,如果React將類或函數作為第一個參數,它將在給定相應道具的情況下檢查其呈現的元素。 React將繼續執行此操作,直到不再有將類或函數作為其第一個參數的createElement調用為止。 讓我們看看實際情況。
function Button ({ addFriend }) { return React.createElement( "button", { onClick: addFriend }, "Add Friend" ) }
function User({ name, addFriend }) { return React.createElement( "div", null, React.createElement( "p", null, name ), React.createElement(Button, { addFriend }) ) }
Above we have two components. A Button and a User. User’s object representation of the DOM will be a “div” with two children, a “p” which wraps the user’s name and a Button component. Now let’s swap out the createElement invocations with what they return,
上面我們有兩個部分。 一個按鈕和一個用戶。 DOM的用戶對象表示形式將是帶有兩個子元素的“ div”,其中包含用戶名的“ p”和一個Button組件。 現在,讓我們將createElement調用與返回的內容交換出去,
function Button ({ addFriend }) { return { type: 'button', props: { onClick: addFriend, children: 'Add Friend' } } }
function User ({ name, addFriend }) { return { type: 'div', props: { children: [{ type: 'p', props: { children: name } }, { type: Button, props: { addFriend } }] } }}
You’ll notice in the above code we have four different type properties, “button”, “div”, “p”, and Button. When React sees an element with a function or class type (like our “type: Button”
above), it will then consult with that component to know which element it returns, given the corresponding props.
您會在上面的代碼中注意到我們有四個不同的類型屬性,即“按鈕”,“ div”,“ p”和“按鈕”。 當React看到一個具有函數或類類型的元素(例如上面的“type: Button”
)時,它會與該組件進行協商以知道它返回了哪個元素,并給出了相應的道具。
With that in mind, at the end of this process, React has a full object representation of the DOM tree. In our example, that will look like this:
考慮到這一點,在此過程結束時,React具有DOM樹的完整對象表示形式。 在我們的示例中,將如下所示:
{ type: 'div', props: { children: [{ type: 'p', props: { children: 'Tyler McGinnis' } }, { type: 'button', props: { onClick: addFriend, children: 'Add Friend' } }] } }
This whole process is called reconciliation in React and it’s triggered every time setState
or ReactDOM.render
are called.
這整個過程在React中稱為對帳,每次調用setState
或ReactDOM.render
都會觸發。
So now let’s again take a look at our initial question that sparked this blog post:
現在,讓我們再次看一下引發此博客文章的最初問題:
At this point we have all the knowledge we need to answer this question, except for one important piece.
至此,我們已經掌握了回答這一問題所需的全部知識,但其中一項重要內容除外。
Odds are if you’ve been using React for any amount of time, you don’t use React.createElement
to create your object representations of the DOM. Instead, you probably use JSX.
奇怪的是,如果您已經使用React一段時間,那么就不要使用React.createElement
來創建DOM的對象表示形式。 相反,您可能使用JSX。
Earlier I wrote: “The primary reason for the confusion is that there’s an often un-talked about abstraction layer between JSX and what’s actually going on in React land.” This abstraction layer is that JSX is always going to get transpiled to React.createElement
invocations, typically via Babel.
早些時候我寫道:“造成混淆的主要原因是,JSX與React領域實際發生的事情之間經常沒有談論抽象層。” 這個抽象層是JSX通常總是 通過Babel 轉換為 React.createElement
調用 。
Looking at our earlier example, this code:
看我們前面的例子,這段代碼:
function Button ({ addFriend }) { return React.createElement( "button", { onClick: addFriend }, "Add Friend" )}
function User({ name, addFriend }) { return React.createElement( "div", null, React.createElement( "p", null, name), React.createElement(Button, { addFriend }) )}
is the result of this JSX being transpiled.
是此JSX被編譯的結果。
function Button ({ addFriend }) { return ( <button onClick={addFriend}>Add Friend</button> )}
function User ({ name, addFriend }) { return ( <div> <p>{name}</p> <Button addFriend={addFriend}/> </div> )}
So finally, what do we call it when we write out our component like this, <Ico
n/>?
所以最后,當我們寫出這樣的組件<Ico
n />時,我們怎么稱呼它?
We can call it “creating an element” because after the JSX is transpiled, that’s exactly what’s happening.
我們可以稱其為“創建元素”,因為在JSX編譯之后,這就是正在發生的事情。
React.createElement(Icon, null)
All of these examples, are “creating an React element”
所有這些示例都是“創建React元素”
React.createElement( 'div', className: 'container', 'Hello!')
<div className='container'>Hello!</div> <Hello />
Thanks for reading! For more on this subject, read React Components, Instances, and Elements by Dan Abramov.
謝謝閱讀! 有關此主題的更多信息,請閱讀Dan Abramov的React組件,實例和元素 。
Follow Tyler McGinnis on Twitter ??Originally published at tylermcginnis.com.
在Twitter上關注Tyler McGinnis?? 最初發布于tylermcginnis.com 。
翻譯自: https://www.freecodecamp.org/news/react-elements-vs-react-components-fdc776705880/
react 組件引用組件