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>
  );
}

 

 

转载于:https://www.cnblogs.com/lindsayzhao103011/p/8618373.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值