react_app 項目開發 (7)_難點集合

/src/App/Admin/Headercss

佈局 import {Row, Col} from "antd"html

<div className="header_box">react

<Row className="header_top">git

<span>歡迎</span>github

<a>退出</a>web

</Row>ajax

<Row className="header_bottom">json

<Col span={4}></Col>跨域

<Col span={20}>數組

<span className="weather_time">時間</span>

<span className="weather_img">圖片</span>

<span className="weather_detail">晴天</span>

</Col>

</Row>

</div>

sysTime = Date.now() / DidMount 中計時器 時間動態顯示

5

import jsonp from jsonp;

MyTools.weather(city){

return new Promise((resolve, reject)=>{

0

})

}

 

  • 根據 path 獲取到 breadcrumb_title 和 父菜單

 

  • 分類列表 - 增長分類 - 修改分類 ---- 熟練對 API 的運用能力

antd 界面 ---- Button、Icon、CardTable(包含分頁)

  • 每一個分類

parentId    一級分類的 parentId 爲 0 

_id    自動生成

name    新分類的名字

__v    自動生成

  • 添加分類返回的響應    

  • 更新狀態 state 是異步的,this.setState({...}, ()=>{...})

注意其第二參數是一個回調函數,在狀態更新完成之後當即執行

  • 對話框不保存上一次的交互記錄,能夠給 Modal 設置一下屬性

  • 關於 Table 的 render 傳值

若是不指定 dataIndex,則第一個參數爲整個對象

若是指定了 dataIndex,則第二個參數爲整個對象,第一個參數爲指定的數據

5

  • 後臺分頁,每次點擊分頁都發請求獲取數據,即便已經獲取過了

優化: 保存每次請求的頁碼即數據

關鍵: 數據結構;通常分頁/搜索分頁

  • this.props.history.push("新頁面", 要傳遞的數據) ---- this.props.history.goBack()

能夠在 "新頁面" 獲取到傳遞的數據

傳遞的數據 = this.props.location.state || {}    // 優化: 保證 數據 始終是一個存在的對象

git 上一個基於 react 的富文本編輯器

RichTextEditor.js

  • import React, { Component } from 'react';
    import { EditorState, convertToRaw } from 'draft-js';
    import { Editor } from 'react-draft-wysiwyg';
    import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
    import draftToHtml from 'draftjs-to-html';
    import htmlToDraft from 'html-to-draftjs';
    
    // import {Card, Button, Icon, Table, message, Modal, Form, Input, Select} from "antd";
    
    import "./css/RichTextEditor.css";
    
    /* 富文本編輯器組件 */
    export default class RichTextEditor extends Component {
        constructor(props){
            super(props);
            this.state = {
                editorState: EditorState.createEmpty()
            }
        }
        
        onEditorStateChange = (editorState) => {
            this.setState({
                editorState,
            });
        };
        
        render() {
            const { editorState } = this.state;
            return (
                <div>
                    <Editor
                        editorState={editorState}
                        wrapperClassName="demo-wrapper"    /* 包裹區類名 */
                        editorClassName="demo-editor"    /* 編輯區類名 */
                        onEditorStateChange={this.onEditorStateChange}
                    />
                    {/*<textarea    // draft2html */}
                        {/*disabled*/}
                        {/*value={draftToHtml(convertToRaw(editorState.getCurrentContent()))}*/}
                    {/*/>*/}
                </div>
            );
        }
    }
  • css/RichTextEditor.css
  • .product_edit  .rdw-dropdown-selectedtext{
        min-width: 54px;
        
        font-size: 16px;
        font-weight: 700;
        letter-spacing: 0;
    }
    
    .rdw-editor-toolbar {
        margin-bottom: 0;
    }
    
    .demo-editor {
        height: 120px;
        padding: 4px;
        
        font-size: 14px;
        line-height: 1.2em;
        letter-spacing: 0;
        background-color: #74878f;
    }

使用:(組件對象,就是標籤對象,意味着可使用 ref 去關聯獲取組件中的屬性和方法。

  • 獲取富文本編輯器最終生成的,html 標籤內容
  • getRichTextEditor = ()=>{
        const {editorState} = this.state;
    return draftToHtml(convertToRaw(editorState.getCurrentContent()); };
  • 父組件給子組件設置 ref ,從而能夠從子組件調用這個方法
  • 編輯商品時,傳遞已有的 detail 給富文本編輯器顯示
  • <div className="rich_text_editor">
        <div className="product_detail_edit">商品詳情:</div>
        <div><RichTextEditor ref="RichTextEditor" detail={product.detail}/></div>
     </div>
  • 默認建立的空文本內容
  • constructor(props){
        super(props);
        this.state = {
            editorState: EditorState.createEmpty()    // 默認建立一個空的文本內容
        }
    }
  • 使用第三方庫,進行 html 到 draft 的轉換
  • componentWillMount(){
        const detail = this.props.detail;
        if(detail){
            const blocksFromHtml = htmlToDraft(detail);    // 將傳過來的 detail 轉換
            const { contentBlocks, entityMap } = blocksFromHtml;
            const contentState = ContentState.createFromBlockArray(contentBlocks, entityMap);
            const editorState = EditorState.createWithContent(contentState);
            this.setState({
                editorState    // 更新界面相關內容
            })
        }
    }
  • 最終的 RichTextEditor.js 組件代碼爲
  • import React, { Component } from 'react';
    import { EditorState, convertToRaw, ContentState} from 'draft-js';
    import { Editor } from 'react-draft-wysiwyg';
    import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
    import draftToHtml from 'draftjs-to-html';
    
    import htmlToDraft from 'html-to-draftjs';    // 將已有的 html 標籤內容,生成一個 draft 內容
    
    import "./css/RichTextEditor.css";
    
    /* 富文本編輯器組件 */
    export default class RichTextEditor extends Component {
        constructor(props){
            super(props);
            this.state = {
                editorState: EditorState.createEmpty()    // 默認建立一個空的文本內容
            }
        }
        
        onEditorStateChange = (editorState) => {
            this.setState({
                editorState,
            });
        };
        
        getRichTextEditor = ()=>{    // 讓父組件調
            const {editorState} = this.state;
            return draftToHtml(convertToRaw(editorState.getCurrentContent()))
        };
        
        componentWillMount(){
            const detail = this.props.detail;
            if(detail){
                const blocksFromHtml = htmlToDraft(detail);    // 將傳過來的 detail 轉換
                const { contentBlocks, entityMap } = blocksFromHtml;
                const contentState = ContentState.createFromBlockArray(contentBlocks, entityMap);
                const editorState = EditorState.createWithContent(contentState);
                this.setState({
                    editorState    // 更新界面相關內容
                })
            }
        }
        
        render() {
            const { editorState } = this.state;
            return (
                <div>
                    <Editor
                        editorState={editorState}    /* 初始顯示文本的內容 */
                        wrapperClassName="demo-wrapper"    /* 包裹區類名 */
                        editorClassName="demo-editor"    /* 編輯區類名 */
                        onEditorStateChange={this.onEditorStateChange}    /* 監聽,實時獲取最新的輸入內容 */
                    />
                    {/*<textarea    // draft2html */}
                        {/*disabled*/}
                        {/*value={draftToHtml(convertToRaw(editorState.getCurrentContent()))}*/}
                    {/*/>*/}
                </div>
            );
        }
    }
  • 經過 ref 能夠獲得標籤對象

由於標籤對象就是組件對象,因此 ref 就能夠獲得組件對象

意味着,父組件調用子組件的方法,能夠 this.refs.ref關聯的名字.方法

  • 在 componentWillMount 能夠直接 this.state.xxx = xxxNew 

5

  • 圖片上傳 - 刪除上傳圖片 name
  • 圖片上傳  ---- form-data ----  image - 選擇文件

返回一個 data 包含了 name 和 服務器資源路徑url

  • 刪除上傳的圖片 ---- x-www-form-urlencoded ---- name - 圖片文件名

antd 組件

管理圖片的組件(上傳/刪除)

  • 父組件給子組件傳 imgs 圖片數組,生成對引用的 fileList,並更新其在 state 中的狀態
  • componentWillMount(){
        const imgs = this.props.imgs;
        if(imgs && imgs.length>0){
            const fileList = imgs.map((img, index)=>({
                uid: -index,
                name: img,
                url: "http://localhost:5000/upload/"+img,
                status: "done",
            }));
            this.setState({
                fileList
            })
        }
    }    // 此時,能夠看到已有的圖片了

  • 須要在 handleChange 上傳圖片完成 file.status: done 時,進行 response 取值,賦值

5

難點: 當用戶 上傳圖片/刪除圖片 後,不進行保存,而是返回時,上傳使得後臺多了冗餘數據,刪除使得數據的丟失

解決:

1. 點擊刪除時,不是真的刪除,而是保存刪除的圖片的名字 到數組 deleteNames 中

---- 當點擊 提交保存 時,再將以前保存的 deleteNames 發送請求,發送 ajax 請求真正地刪除

2. 點擊上傳時,真的上傳了,同時保存下上傳的圖片的名字 到數組 fackNames 中

---- 當點擊 返回 ←  時, 發送 ajax 請求 刪除 以前保存的 fackNames 

難點: 添加一條角色到後臺,而後如何不發送獲取列表的請求,來刷新頁面

解決: 經過 name 添加到角色到, 後臺返回一個角色的相關信息,能夠將這個 role 角色對象,存入 roles 狀態中

如此的問題在於,優化: 是 Component 始終在 setState 後 render

仍是用 PureComponent + [...this.state.狀態]去 淺拷貝 生成新狀態來 激活 render

5

5

5

5

5

5

5

相關文章
相關標籤/搜索