• react imvc简介


    1. IMVC的I是Isomorphic的缩写,意思是同构,指一份JS代码既可以在Node.js运行也可以在Browser里运行
        1》M是Model,指状态以及状态变化的函数的集合,由initialState状态和actions函数组成
        2》V是View的缩写,React组件
        3》C是Controller的缩写,指包含生命周期方法、事件处理器、同构工具方法及负责同步View和Model的中间媒介
        4》在react-imvc的Model中state是immutable data、action是pure function,View是React.js建议尽可能使用function stateless component写法。所有跟外界的交互比如:Life-Cycle method、Ajax/Fetch、Event Handler时间处理器、localStorage等都放在Controller里。

    2. Controller的一些重要属性
        1》View是React Component组件,该组件的props结构如下:
              props.state是controller.store.getState()里的global state状态树
              props.handlers是controller实例里以handleXXX形式定义的事件处理器的集合对象
              props.actions是controller.store.actions里的actions集合对象
         2》Model属性是一个对象,除了initialState属性外其余都是pure function
         3》preload对象用来在页面显示前预加载css、json等数据
         4》handlers在初始化时从controller的实例里收集以handle开头以箭头函数形式定义的方法的集合对象,用来传递给controller.View组件

    3. Controller的一些重要方法
         1》Event handler

    import React from 'react'
    import Controller from 'react-imvc/controller'
    
    export default class extends Controller {
        View = View
        initialState = {
            count: 0,
        }
        actions = {
            INCREMENT: state => ({ ...state, count: state.count + 1 }),
            DECREMENT: state => ({ ...state, count: state.count - 1 }),
            CHANGE_BY_NUM: (state, num) => ({ ...state, count: state.count + Number(num) })
        }
        // 事件处理器必须使用 arrow function 箭头函数的语法
        handleIncre = () => {
            let { INCREMENT } = this.store.actions
            INCREMENT()
        }
        // 事件处理器里使用 action 更新 global state
        handleDecre = () => {
            let { DECREMENT } = this.store.actions
            DECREMENT()
        }
        // 将特殊的索引如 index, id 或者其他信息,缓存在 DOM attribute 里
        // 在事件处理器里,从 DOM attribute 里取回
        handleCustomNum = event => {
            let { CHANGE_BY_NUM } = this.store.actions
            let num = event.currentTarget.getAttribute('data-num')
            CHANGE_BY_NUM(num)
        }
    }
    
    /**
    * 在 view 组件里,可以从 props 里拿到 global state 和 global event handlers
    */
    function View({ state, handlers }) {
        let { handleIncre, handleDecre, handleCustomNum } = handlers
        return (
            <div>
                <h1>Count: {state.count}</h1>
                <button onClick={handleIncre}>+1</button>
                <button onClick={handleDecre}>-1</button>
                <button onClick={handleCustomNum} data-num={10}>+10</button>
            </div>
        )
    }

         2》handleInputChange(path, value, oldValue) -> final value
         3》Style组件将controller.preload里配置的css展示在页面上

    import React from 'react'
    import Controller from 'react-imvc/controller'
    import { Style } from 'react-imvc/component' // 加载 Style 组件
    
    export default class extends Controller {
        preload = {
            'main': 'path/to/css' // 配置 css 文件路径
        }
        View = View
    }
    
    // 当组件渲染时,Style 标签会将 preload 里的同名 css 内容,展示为 style 标签。
    function View() {
        return (
            <div>
              <Style name="main" />
            </div>
        )
    }

        4》Input组件用来将表单跟store联系起来

    import React from 'react'
    import Controller from 'react-imvc/controller'
    import { Input } from 'react-imvc/component' // 加载 Input 组件
    
    export default class extends Controller {
        View = View
        // 可以在 Controller 里直接写 initialState
        initialState = {
            // 多层次对象
            user: {
                name: {
                    first: '',
                    last: '',
                },
                email: '',
                age: 0
            },
            // 数组对象
            friends: [{
                name: 'friendA',
            }, {
                name: 'friendB',
            }],
            // 复合对象
            phone: {
                value: '',
                isValid: false,
                isWarn: false,
            },
            content: ''
        }
    }
    
    /**
    * Input 组件支持 path 写法,支持数组
    * 可以用 .:/ 三种分隔符书写 path
    * 不需要写 value,Input 组件会使用以下属性:
    * 1》使用 transformer 属性可以在更新 store 之前做数据处理,接受两个参数 transformer(newValue, oldValue),其返回值将作为最后更新到 store 的 value。
    * 2》使用 check 属性,可以验证字段。当 Input 组件传入了 check 属性时,它将被视为复合对象 { value, isValid, isWarn } 三个属性,它有以下行为:
    *            - 当用户 blur 脱离表单焦点时,使用 check 函数检查 value 值,如果 check 函数返回 true,则 isValid = true,isWarn = false。
    *            - 当用户 focus 聚焦表单时,取消 isWarn = false 的状态。
    *            - 在将 input.value 更新到 store 时,会自动补全 `${name}.value` 更新 state。
    * 3》使用 as 属性,可以自定义渲染标签.input 组件默认渲染为 input 标签,可以使用 as 属性将它渲染成 textarea 标签或其他可以触发 onChange 方法的组件。
    */
    function View({ state }) {
        return (
            <div>
                firstname: <Input name="user.name.first" />
                lastname: <Input name="user:name:last" />
                email: <Input name="user/email" />
                age: <Input name="user.age" transformer={Number} >
                friends: {
                    state.friends.map((friend, index) => {
                        return (
                            <div>
                                name: <Input name={`friends/${index}/name`} />
                            </div>
                        )
                    })
                }
                phone: <Input name="phone" check={isValidPhone} />
                content: <Input as="textarea" name="content" />
            </div>
        )
    }

    3. Controller中重要的生命周期方法

        .》shouldComponentCreat()方法触发时view还未被创建渲染,主要用于鉴定权限,如果用户没有权限访问该页面,可以通过 this.redirect 方法,重定向到其他页面。
        .》componentWillCreate()方法触发时view还未被创建渲染,可在方法内调用接口获取首屏数据
        .》componentDidFirstMount() 方法触发时用户已经看到了首屏,可在方法内调用接口获取非首屏数据。
        .》componentDidMount()方法触发时component已经mount到页面,可在方法内进行DOM操作等浏览器相关活动
        .》
    componentWillUnmount()方法触发时component即将从页面unmount,解绑计时器等跟componentDidMount相关的逆操作
        .》stateDidChange(data)方法触发时store里的state发生变化并且view也重新渲染,data中为actionType, actionPayload, previousState, currentState 

    4. 高阶组件connect(selector)(ReactComponent)
         connect是一个高阶函数,第一次调用时接受selector函数作为参数返回withData函数。withData函数接受一个React组件作为参数返回一个新的React组件。withData会将selector函数返回的数据作为props传入新的React组件。selector({state, handlers, actions})函数得到一个data参数包含三个字段,分别对应controller里的global state, global handlers和actions对象

    import React from "react";
    import connect from 'react-imvc/hoc/connect'
    
    const withData = connect(({ state }) => {
      return {
        content: state.loadingText
      }
    })
    
    export default withData(Loading)
    
    function Loading(props) {
      if (!props.content) {
        return null;
      }
      return (
        <div id="wxloading" className="wx_loading">
          <div className="wx_loading_inner">
            <i className="wx_loading_icon" />
            {props.content}
          </div>
        </div>
      );
    }

     

  • 相关阅读:
    verilog BRAM 读写
    verilog 语法一 led 翻转
    面试 遇到 问题
    S32K144+UJA1169 (四 ) S32K144 SPI1 功能初始化
    S32K144+UJA1169 ( 三 ) S32K144 SPI1 功能初始化
    S32K144+UJA1169 ( 二 ) S32K144 SPI1 对应的引脚 初始化 为 SPI 功能
    S32K144+UJA1169 ( 一 ) 连接框架+1169 功能 说明
    编译 xboot
    make clean make[1]:sdl2-config:命令未找到
    lwip 内存配置和使用,以及 如何 计算 lwip 使用了多少内存?
  • 原文地址:https://www.cnblogs.com/lindsayzhao103011/p/8618373.html
Copyright © 2020-2023  润新知