指令

指令即为在html元素开标签内编写的自定义属性,类似于VueAngular中的指令。语法为<element #exTag="value">,用它可以封装一些实用功能,目的是写更少的代码去做更多的事情。在NornJ中,指令实质上是标签的一种特殊写法:

<div #show="{false}"></div>

完全等价于:

<div>
  <#props>
    <#show>
      {false}
    </#show>
  </#props>
</div>

内置指令

目录

show

类似于Vuev-show指令,#show用于切换元素是否显示,原理为修改style:

const html = nj`
<div #show="{{isShow}}">
  test inline extension tag
</div>
`({ isShow: false });

console.log(html);  //<div style="display:none">test inline extension tag</div>

mobx-bind

类似于Vuev-model指令,可以使用#mobx-bind配合Mobx<input><textarea>等表单元素上创建双向数据绑定,它会根据控件类型自动选取正确的方法来更新元素。

  • 在线示例(jsfiddle)

source code

import { Component } from 'react';
import { observable } from 'mobx';
import nj from 'nornj';

class TestComponent extends Component {
  @observable inputValue = '';

  render() {
    return nj`
      <input :#mobx-bind="inputValue">
    `(this);
  }
}

如上所示,无需编写<input>标签的onChange事件,inputValue变量已自动和<input>标签建立了双向数据绑定的关系。点这里是一个#mobx-bind结合表单组件的示例页面。

  • 实质上,#mobx-bind的实现原理和v-model很类似,上述示例其实就是下面的语法糖形式:
class TestComponent extends Component {
  @observable inputValue = '';
  @autobind
  onChange(e) {
    this.inputValue = e.target.value;
  }

  render() {
    return nj`
      <input value={inputValue} {onChange}>
    `(this);
  }
}
  • #mobx-bind#mst-bind存放在nornj-react包中,需要按如下方式引入后方可使用:
import 'nornj-react/mobx';

另外如果使用nornj-loader,则需要在Webpack的配置中引入相应的扩展配置文件

module: {
  rules: [
    {
      test: /\.t.html(\?[\s\S]+)*$/,
      use: [{
        loader: 'nornj-loader',
        options: {
          outputH: true,
          delimiters: 'react',
          extensionConfig: require('nornj-react/mobx/extensionConfig')
        }
      }]
    },
    ...
  ]
}
  • onChange事件

由于#mobx-bind默认自动设置了组件的onChange事件,但有些情况下我们可能还是需要在onChange中做一些其他的操作:

class TestComponent extends Component {
  @observable inputValue = '1';

  @autobind
  onChange(e) {
    console.log(e.target.value);
  }

  render() {
    return nj`
      <input :#mobx-bind="inputValue" {onChange}>
    `(this);
  }
}

如上所示,onChange事件的行为和标签原生的onChange完全相同,它会在文本框的值变化后执行。

  • 使用action更新变量

mobx开发中如果启动严格模式或者使用mobx-state-tree时,则须要使用action来更新变量。可按下面方式配置使用action

import { observable, action, configure } from 'mobx';

// don't allow state modifications outside actions
configure({enforceActions: true});

class TestComponent extends Component {
  @observable inputValue = '1';

  @action.bound
  setInputValue(v) {
    this.inputValue = v;
  }

  render() {
    return nj`
      <input :#mobx-bind.action="inputValue">
    `(this);
  }
}

当有action修饰符时,#mobx-bind会默认执行camel命名法(set + 变量名)定义的action,上例中为setInputValue

mst-bind

#mst-bind即为#mobx-bind的默认使用action来更新值的版本,用来配合mobx-state-tree的变量使用:

store:

import { types } from "mobx-state-tree";

const TestStore = types.model("TestStore",
  {  
    inputValue: '1'
  })
  .actions(self => ({
    setInputValue(v) {
      self.inputValue = v;
    }
  }));

component:

@inject('rootStore')
@observer
class TestComponent extends Component {
  render() {
    return nj`
      <input :#mst-bind="testStore.inputValue">
    `({
      testStore: this.props.rootStore.testStore
    });
  }
}

如上,#mst-bind会默认执行camel命名法(set + 变量名)定义的action来更新值,上例中为setInputValue。除此外#mst-bind的其他特性与上述的#mobx-bind完全相同。

目前mobx-bind和mst-bind默认支持的控件列表

控件名称 控件类型 备注
<input> 原生 <input type="checkbox"><input type="radio">暂时不支持
<textarea> 原生
<select> 原生 <select multiple>暂时不支持
<ant-input> Ant Design
<ant-input.textarea>
<ant-textarea>
Ant Design
<ant-checkbox> Ant Design
<ant-checkbox.group>
<ant-checkboxgroup>
Ant Design
<ant-radio.group> Ant Design
<ant-switch> Ant Design
<ant-select> Ant Design <ant-select mode="multiple">暂时不支持
<ant-cascader> Ant Design
<ant-datepicker>
<ant-datepicker.monthpicker>
<ant-datepicker.weekpicker>
<ant-datepicker.rangepicker>
<ant-monthpicker>
<ant-weekpicker>
<ant-rangepicker>
Ant Design
<el-input> Element-React
<el-select> Element-React <el-select multiple>暂时不支持
<el-datepicker> Element-React
<el-daterangepicker> Element-React
<el-timeselect> Element-React
<el-timepicker> Element-React
<el-timerangepicker> Element-React
<el-switch> Element-React
<el-checkbox> Element-React
<el-checkbox.group> Element-React
<el-radio.group> Element-React
<el-cascader> Element-React  

results matching ""

    No results matching ""