今天在练习React构建组件的时候遇到一个问题。
由于文档中反复提倡将组件尽可能按功能单位分解复用。在练习用React做一个todolist时候,我把todolist分解成两部分:
class Todolist = class Writedown + class Todo;
其中 class Writedown返回 一个input和一个button 以接收和确定 用户输入的文本。
class Todo 是一个li,展示todo事项并带有删除事项的span。之所以抽取li标签作为Todo组件是考虑到以后扩展功能,如对单个事项添加修改文本、置顶、标记已完成等等。
但是在写完class Todo的时候发现检测工具却报错,说Todolist的constructor构造器出现Syntax Error。
Are you kdding me?
最后发现是 class Todo 引发的问题,这次的报错完全不真实,并误导了我。。反复排查,我怀疑是render返回的JSX受到HTML类型约束.
在vue中,我们的自定义组件也一样,当DOM模板解析时,也受到HTML的限制,在table、ul等元素中限制了其包裹的html标签:
<table><tr is="my-row"></tr></table>
我们只能在tr 中用借用is特性绑定自定义组件my-row。
我这次在子组件中返回li,React居然报错说我有个syntax error,并指出是unexpected token,真是一脸懵逼。。。。
----------------------------------------------------------------------------------------
但是在官网中,有个例子是function组件返回li,这让我很疑惑。https://facebook.github.io/react/docs/lists-and-keys.html#extracting-components-with-keys.
这问题先记下,这两天弄清楚。
----------------------9月4号晚 更新--------------------------------
然后发现。。返回li确实没有问题。。。
这实在是最难接受的情况了。浏览器不再报错,但是代码结构是和原来差不多的。
1 class Write extends React.Component { 2 constructor(props){ 3 super(props); 4 this.handle=this.handle.bind(this); 5 } 6 handle(){ 7 const text=document.getElementById('todoIn').value; 8 this.props.onWriteDown(text); 9 } 10 render(){ 11 return ( 12 <div> 13 <input type="text" id="todoIn" /> 14 <button onClick={this.handle}>confirm</button> 15 </div> 16 ); 17 } 18 } 19 //Todo组件输出li,接收delete方法 20 class Todo extends React.Component { 21 constructor(props){ 22 super(props); 23 this.handle=this.handle.bind(this); 24 } 25 handle(){ 26 } 27 render(){ 28 return ( 29 <li onClick={this.props.onDel}>{this.props.mes}</li> 30 ); 31 } 32 } 33 34 //Todolist组件,用todolist数组操作、存储事项,交互后赋值给state,也就是说state接收的是副本。 35 class Todolist extends React.Component { 36 constructor (props) { 37 super(props); 38 this.n=0; 39 this.state={list:[]}; 40 this.todolist=[]; 41 this.handle=this.handle.bind(this); 42 this.handle_del=this.handle_del.bind(this); 43 } 44 handle (m) { 45 this.todolist.push({thing:m,vid:this.n++}); 46 this.setState({list:this.todolist}); 47 } 48 handle_del (id) { 49 let d =0; 50 this.todolist.forEach((v,i)=>{ 51 if(v.vid==id){ 52 d=i; 53 } 54 }); 55 this.todolist.splice(d,1); 56 this.setState({list:this.todolist}); 57 } 58 render(){ 59 var that = this; 60 var todo=[]; 61 this.state.list.forEach(function(v,i,a){ 62 let id = v.vid.toString(); 63 console.log(v.thing) 64 let temp=<Todo key={id} onDel={() => that.handle_del(id)} mes={v.thing} ></Todo>; 65 todo.push(temp); 66 }); 67 return( 68 <div> 69 <Write onWriteDown={this.handle} /> 70 <ul> 71 {todo} 72 </ul> 73 </div> 74 ); 75 } 76 } 77 78 ReactDOM.render( 79 <Todolist />, 80 document.getElementById('example') 81 );
不过现在可以确定的是,JSX的可以输出li、tr等。