Skip to content

Commit 71cec7e

Browse files
committed
update readme
1 parent 7e98ada commit 71cec7e

File tree

4 files changed

+2316
-1502
lines changed

4 files changed

+2316
-1502
lines changed

README.ZH-CN.md

Lines changed: 385 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,385 @@
1+
# babel-plugin-react-directives
2+
一个给react(任何JSX)提供一些类似vue指令的Babel转换插件
3+
4+
[![Travis (.org) branch](https://img.shields.io/travis/peakchen90/babel-plugin-react-directives/master.svg)](https://travis-ci.org/peakchen90/babel-plugin-react-directives)
5+
[![Codecov](https://img.shields.io/codecov/c/github/peakchen90/babel-plugin-react-directives.svg)](https://codecov.io/gh/peakchen90/babel-plugin-react-directives)
6+
[![npm](https://img.shields.io/npm/v/babel-plugin-react-directives.svg)](https://www.npmjs.com/package/babel-plugin-react-directives)
7+
[![GitHub](https://img.shields.io/github/license/mashape/apistatus.svg)](https://github.com/peakchen90/babel-plugin-react-directives/blob/master/LICENSE)
8+
9+
> [English document](./README.md)
10+
11+
## 开始使用
12+
13+
需要 **node v8.6.0** 或者更高版本,**babel v6.20.0** 或者更高版本
14+
15+
### 安装
16+
使用 npm:
17+
```bash
18+
npm install --save-dev babel-plugin-react-directives
19+
```
20+
21+
使用 yarn:
22+
```base
23+
yarn add --dev babel-plugin-react-directives
24+
```
25+
26+
### 添加配置 `.babelrc`
27+
```json
28+
{
29+
"plugins": [
30+
"react-directives"
31+
]
32+
}
33+
```
34+
35+
### 插件选项
36+
37+
默认选项:
38+
```json5
39+
{
40+
"prefix": "x",
41+
"pragmaType": "React"
42+
}
43+
```
44+
45+
- `prefix`: 指令的 props 前缀,默认值: "x",用法示例: `x-if`
46+
- `pragmaType`: 帮助内部进行正确的识别一些语法,如 hooks,默认值为: "React"
47+
48+
## 指令
49+
50+
### x-if
51+
如果 `x-if` 的值为**真值**,则将渲染此元素,否则不渲染。
52+
53+
**例子:**
54+
```jsx harmony
55+
const foo = <div x-if={true}>text</div>
56+
```
57+
58+
**转换成:**
59+
```jsx harmony
60+
const foo = true ? <div>text</div> : null
61+
```
62+
63+
### x-else-if 和 x-else
64+
`x-else-if` 的同一层级元素必须有相对应的 `x-if`,如果 `x-if` 的值是**假值**,并且 `x-else-if` 的值是**真值**,则它将被渲染。
65+
66+
`x-else` 的同一层级元素必须有相对应的 `x-if``x-else-if`,当 `x-if` 或者 `x-else-if` 都是**假值**时,它将被渲染。
67+
68+
**例子:**
69+
```jsx harmony
70+
const foo = (
71+
<div>
72+
<p x-if={data === 'a'}>A</p>
73+
<p x-else-if={data === 'b'}>B</p>
74+
<p x-else-if={data === 'c'}>C</p>
75+
<p x-else>D</p>
76+
</div>
77+
)
78+
```
79+
80+
**转换成:**
81+
```jsx harmony
82+
const foo = (
83+
<div>
84+
{data === 'a'
85+
? <p>A</p>
86+
: data === 'b'
87+
? <p>B</p>
88+
: data === 'c'
89+
? <p>C</p>
90+
: <p>D</p>
91+
}
92+
</div>
93+
)
94+
```
95+
### x-show
96+
97+
`x-show` 通过 `style` prop 的 `display` 属性来控制元素的显示或隐藏,如果 `x-show` 的值是**假值**,则设置 `style.display = "none"`,否则给不设置。
98+
99+
**例子:**
100+
```jsx harmony
101+
const foo = <div x-show={true}>text</div>
102+
```
103+
104+
**转换成:**
105+
```jsx harmony
106+
const foo = (
107+
<div style={{
108+
display: true ? undefined : "none"
109+
}}>text
110+
</div>
111+
)
112+
```
113+
114+
当然,它还将合并其他 `style`,例如:
115+
```jsx harmony
116+
const foo = (
117+
<div
118+
style={{ color: 'red' }}
119+
x-show={true}
120+
{...extraProps}>
121+
text
122+
</div>
123+
)
124+
```
125+
126+
将被转换成:
127+
```jsx harmony
128+
const foo = (
129+
<div
130+
{...extraProps}
131+
style={{
132+
...{ color: 'red' },
133+
...(extraProps && extraProps.style),
134+
display: true ? undefined : "none"
135+
}}>text
136+
</div>
137+
)
138+
```
139+
140+
### x-for
141+
使用 `x-for` 遍历数组生成元素。
142+
143+
绑定的值应该像这样: `(item, index) in list`
144+
- `list`: 遍历的目标数组
145+
- `item`: 当前的值
146+
- `index`: 当前的索引
147+
148+
提示: `index` 是可选的, 如果不需要 `index` 可以这样用: `item in list`
149+
150+
**例子:**
151+
```jsx harmony
152+
const foo = (
153+
<ul>
154+
<li
155+
x-for={item in list}
156+
key={item.id}>{item.name}
157+
</li>
158+
</ul>
159+
)
160+
```
161+
162+
**转换成:**
163+
```jsx harmony
164+
const foo = (
165+
<ul>
166+
{list.map(item => (
167+
<li key={item.id}>{item.name}</li>
168+
))}
169+
</ul>
170+
)
171+
```
172+
173+
另请请注意,如果与 `x-if` 一起使用,则 `x-for` 拥有更高的优先级,例如:
174+
```jsx harmony
175+
const foo = (
176+
<ul>
177+
<li
178+
x-for={item in list}
179+
x-if={item.name === 'alice'}
180+
key={item.id}>{item.name}
181+
</li>
182+
</ul>
183+
)
184+
```
185+
186+
将被转换成:
187+
```jsx harmony
188+
const foo = (
189+
<ul>
190+
{list.map(item => (
191+
item.name === 'alice'
192+
? <li key={item.id}>{item.name}</li>
193+
: null
194+
))}
195+
</ul>
196+
)
197+
```
198+
199+
### x-model
200+
`x-model` 是类似于 vue `v-model` 的语法糖,使用时绑定一个值到表单元素的 `value` prop 上,在表单元素更新时自动更新状态。
201+
202+
**例子:**
203+
```jsx harmony
204+
class Foo extends React.Component {
205+
constructor(props) {
206+
super(props);
207+
this.state = { data: 'text' }
208+
}
209+
210+
render() {
211+
return <input x-model={this.state.data}/>
212+
}
213+
}
214+
```
215+
216+
**转换成:**
217+
```jsx harmony
218+
class Foo extends React.Component {
219+
constructor(props) {
220+
super(props);
221+
this.state = {
222+
data: 'text'
223+
};
224+
}
225+
226+
render() {
227+
return (
228+
<input
229+
value={this.state.data}
230+
onChange={(..._args) => {
231+
let _value = _args[0] && _args[0].target && typeof _args[0].target === "object"
232+
? _args[0].target.value
233+
: _args[0];
234+
235+
this.setState(_prevState => {
236+
return { data: _value };
237+
});
238+
}}
239+
/>
240+
);
241+
}
242+
}
243+
```
244+
245+
当存在其他 `onChange` prop 时,将会合并这些 prop 上绑定的方法:
246+
```jsx harmony
247+
class Foo extends React.Component {
248+
constructor(props) {
249+
super(props);
250+
this.state = { data: 'text' }
251+
}
252+
253+
onChange(e) {
254+
console.log(e.target.value);
255+
}
256+
257+
render() {
258+
return (
259+
<input
260+
onChange={this.onChange.bind(this)}
261+
x-model={this.state.data}
262+
{...this.props}
263+
/>
264+
)
265+
}
266+
}
267+
```
268+
269+
将被转换成:
270+
```jsx harmony
271+
class Foo extends React.Component {
272+
constructor(props) {
273+
super(props);
274+
this.state = { data: 'text' };
275+
}
276+
277+
onChange(e) {
278+
console.log(e.target.value);
279+
}
280+
281+
render() {
282+
return (
283+
<input
284+
{...this.props}
285+
value={this.state.data}
286+
onChange={(..._args) => {
287+
let _value = _args[0] && _args[0].target && typeof _args[0].target === "object"
288+
? _args[0].target.value
289+
: _args[0];
290+
291+
this.setState(_prevState => {
292+
return { data: _value };
293+
});
294+
295+
let _extraFn = {
296+
...{ onChange: this.onChange.bind(this) },
297+
...(this.props && this.props.onChange)
298+
}.onChange;
299+
typeof _extraFn === "function" && _extraFn.apply(this, _args);
300+
}}
301+
/>
302+
);
303+
}
304+
}
305+
```
306+
307+
如果 `x-model` 的值是一个对象上的属性,那么当表单元素更新时将创建一个新对象,并合并对象上旧的属性值,比如:
308+
```jsx harmony
309+
class Foo extends React.Component {
310+
constructor(props) {
311+
super(props);
312+
this.state = {
313+
data: {
314+
text: 'bar'
315+
}
316+
}
317+
}
318+
319+
render() {
320+
const { data } = this.state;
321+
return <input x-model={data.text}/>
322+
}
323+
}
324+
325+
```
326+
将被转换成:
327+
```jsx harmony
328+
class Foo extends React.Component {
329+
constructor(props) {
330+
super(props);
331+
this.state = {
332+
data: { text: 'bar' }
333+
};
334+
}
335+
336+
render() {
337+
const { data } = this.state;
338+
return (
339+
<input
340+
value={data.text}
341+
onChange={(..._args) => {
342+
let _value = _args[0] && _args[0].target && typeof _args[0].target === "object"
343+
? _args[0].target.value
344+
: _args[0];
345+
346+
this.setState(_prevState => {
347+
let _val = {
348+
..._prevState.data,
349+
text: _value
350+
};
351+
return {
352+
data: _val
353+
};
354+
});
355+
}}/>
356+
);
357+
}
358+
}
359+
```
360+
361+
当然也可以使用 `useState` hook 方式:
362+
```jsx harmony
363+
function Foo() {
364+
const [data, setData] = useState(0);
365+
return <input x-model={data}/>
366+
}
367+
```
368+
369+
将被转换成:
370+
```jsx harmony
371+
function Foo() {
372+
const [data, setData] = useState(0);
373+
return (
374+
<input
375+
value={data}
376+
onChange={(..._args) => {
377+
let _value = _args[0] && _args[0].target && typeof _args[0].target === "object"
378+
? _args[0].target.value
379+
: _args[0];
380+
381+
setData(_value);
382+
}} />
383+
);
384+
}
385+
```

0 commit comments

Comments
 (0)