--- title: React - 三大屬性 Refs tags: React date: 2021/8/4 --- ###### tags: `React` ###### *date: 2021/8/4* # ⚛️ React - 三大屬性 **Refs** [TOC] ## React 起手式 - 老規矩,先建立一個 HTML,並搭建好環境 :::spoiler 還不知道起手式請點我 ```htmlembedded= <div id="container"></div> <script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script> <script type="text/babel"> </script> ``` ::: ## 創建組件 1. 在 script 中,要引用 React 的三大屬性,必須使用類式組件。 ```jsx=+ class Dream extends React.Component { render(){ // 需注意標籤閉合 return ( <div> <input type="text" placeholder="輸入你的夢想"/><br/> <button>點擊</button> </div> ) } } ReactDOM.render( <Dream/>, document.getElementById( 'container' ) ) ``` ![show](https://i.imgur.com/Li5QE8n.png) *畫面呈現* 2. 幫按鈕新增點擊事件 ```jsx=10 class Dream extends React.Component { // 使用賦值語句 + 箭頭函式 showDream = () => { console.log( '你點擊按鈕了!!!' ); } // 注意 onClick 為 React 給的方法,需注意大小寫 render(){ return ( <div> <input type="text" placeholder="輸入你的夢想"/><br/> <button onClick={ this.showDream }>點擊</button> </div> ) } } ReactDOM.render( <Dream/>, document.getElementById( 'container' ) ) ``` ![click](https://i.imgur.com/UL7nww9.gif) *畫面呈現* 3. 讓點擊事件能過獲取到`input`裡面的值 - 原生 JS 是利用`document.getElementById('id_name')` - jQuery 則是利用`$('#id_name')` - React 本身也有提供 ref 來取得值 ## Refs 取得的三種方式 ### 字串型態的 Ref ( 不推薦:未來 React 可能會廢棄掉 :-1:) - 在要取得的節點設置一個`ref="your_id"` - 並利用`this.refs`取得節點 ```jsx=10 class Dream extends React.Component { showDream = () => { // 取得節點 const { dream } = this.refs alert( `祝你 ${dream.value} 夢想成真` ) } // 在 input 裡添加 ref="dream" render(){ return ( <div> <input ref="dream" type="text" placeholder="輸入你的夢想"/><br/> <button onClick={ this.showDream }>點擊</button> </div> ) } } ReactDOM.render( <Dream/>, document.getElementById( 'container' ) ) ``` ![alert](https://i.imgur.com/zqncGMd.gif) ### 回調形式的 Ref - 使用回調形式的箭頭函數取得當前節點`( currentNode ) => { this.your_id = currentNode }` - 因為使用回調形式,所以可以透過 this 取得屬性 ```jsx=10 class Dream extends React.Component { showDream = () => { const { dream } = this alert( `祝你 ${dream.value} 夢想成真` ) } // 在 input 裡使用回調形式的箭頭函數取得節點 // 利用箭頭函數的 this 向外找的特性綁定到實例自己身上 // 箭頭函數左側如果只有一個參數,可以省略括弧 // 箭頭函數右側如果只有一句函數,可以省略括弧 render(){ return ( <div> <input ref={ c => this.dream = c } type="text" placeholder="輸入你的夢想"/> <br/> <button onClick={ this.showDream }>點擊</button> </div> ) } } ReactDOM.render( <Dream/>, document.getElementById( 'container' ) ) ``` ==注意==: > 如果是使用行內函數的回調方式,會再更新頁面時,行內回調函數會被呼叫兩次,第一次是 null,第二次就是用 DOM,這過程是為了清空函數並重新賦予,大多數情況下並不會有什麼影響,如果想避免出現這個情況,可以用類綁定的函數解決 > [name=React - Refs & DOM] #### 類綁定的回調函數 - 這樣更新畫面也不會一直呼叫函數了 ```jsx=10 class Dream extends React.Component { showDream = () => { const { dream } = this alert( `祝你 ${dream.value} 夢想成真` ) } // 類綁定的回調函數 saveDream = (c) => { this.dream = c } render(){ // 改成使用函數 return ( <div> <input ref={ this.saveDream } type="text" placeholder="輸入你的夢想"/> <br/> <button onClick={ this.showDream }>點擊</button> </div> ) } } ReactDOM.render( <Dream/>, document.getElementById( 'container' ) ) ``` ### createRef 的使用 ( 目前 React 最推薦使用的方式 :+1:) - 使用 createRef 創建一個容器,並掛在實例自身 - 容器跟 id 一樣,同個名字只能設定一個 ```jsx=10 class Dream extends React.Component { // 使用 createRef() 創建容器 dreamRef = React.createRef() showDream = () => { const { dreamRef } = this // 必須使用 current 來取得當前節點 alert( `祝你 ${dreamRef.current.value} 夢想成真` ) } render(){ // 改成使用 createRef 的方式 return ( <div> <input ref={ this.dreamRef } type="text" placeholder="輸入你的夢想"/> <br/> <button onClick={ this.showDream }>點擊</button> </div> ) } } ReactDOM.render( <Dream/>, document.getElementById( 'container' ) ) ``` ## 總結 Refs 1. refs 最簡單的寫法就是字串形式寫法 ( 不推薦使用 :-1: ) 2. 回調形式的 refs 雖麻煩一點,但比較不會出現奇怪的錯誤 3. createRef 雖最麻煩,但官方網站最推薦使用 ### 參考資料 - [React 官網 - Refs & DOM](https://zh-hant.reactjs.org/docs/refs-and-the-dom.html) - [React 全家桶](https://www.youtube.com/playlist?list=PLmOn9nNkQxJFJXLvkNsGsoCUxJLqyLGxu)