指令
指令即为在html元素开标签内编写的自定义属性,类似于Vue及Angular中的指令。语法为<element #exTag="value">,用它可以封装一些实用功能,目的是写更少的代码去做更多的事情。在NornJ中,指令实质上是标签的一种特殊写法:
<div #show="{false}"></div>
完全等价于:
<div>
<#props>
<#show>
{false}
</#show>
</#props>
</div>
内置指令
目录
show
类似于Vue的v-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
类似于Vue的v-model指令,可以使用#mobx-bind配合Mobx在<input>及<textarea>等表单元素上创建双向数据绑定,它会根据控件类型自动选取正确的方法来更新元素。
- 在线示例(jsfiddle)
基本使用方法
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 |