React学习之进阶JSX语法(十一)

前端之家收集整理的这篇文章主要介绍了React学习之进阶JSX语法(十一)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

1.再顾JSX语法

从我第一篇博客来看,JSX其实就是提供了一个实现React.createElement(component,props,...children)函数的便捷方法

<MyButton color="blue"@H_502_14@ shadowSize={2@H_502_14@}>
  Click Me
</MyButton>@H_502_14@

React编译完后就形成了

React.createElement(
  MyButton,{color@H_502_14@: 'blue'@H_502_14@,shadowSize: 2@H_502_14@},'Click Me'@H_502_14@
)

所以注意,第一个参数不一定是一个DOM参数,只要是一个JSX组件或者是DOM标签

当然如果你不加入子内容的话

<div className="sidebar"@H_502_14@ />

直接闭合标签即可

编译后

React.createElement(
  'div'@H_502_14@,{className: 'sidebar'@H_502_14@},null@H_502_14@
)

2.不要试图用属性访问符来构造JSX组件

const@H_502_14@ MyComponents = {
  DatePicker: function@H_502_14@ DatePicker@H_502_14@(props)@H_502_14@ {@H_502_14@
    return@H_502_14@ <div@H_502_14@>@H_502_14@Imagine a {props.color} datepicker here.</div@H_502_14@>@H_502_14@;@H_502_14@
  }
}

function@H_502_14@ BlueDatePicker@H_502_14@()@H_502_14@ {@H_502_14@
//Warning : no allowed@H_502_14@
  return@H_502_14@ <MyComponents.DatePicker@H_502_14@ color@H_502_14@="blue"@H_502_14@ />@H_502_14@;@H_502_14@
}

这种使用.属性访问符进行构建JSX组件虽然不会报错,但是不允许

3.用户自定义的组件名必须是大写的

function@H_502_14@ hello@H_502_14@(props)@H_502_14@ {@H_502_14@
  return@H_502_14@ <div@H_502_14@>@H_502_14@Hello {props.toWhat}</div@H_502_14@>@H_502_14@;@H_502_14@
}

function@H_502_14@ HelloWorld@H_502_14@()@H_502_14@ {@H_502_14@
  return@H_502_14@ <hello@H_502_14@ toWhat@H_502_14@="World"@H_502_14@ />@H_502_14@;@H_502_14@
}

方法是不会有任何输出

至于为什么之前的博客也讲过,DOM元素才能用小写,其他的都应该用大写。

如果你已经将一个组件的名字写成了小写,可以将它赋值给一个大写的变量即可

function@H_502_14@ HelloWorld@H_502_14@()@H_502_14@ {@H_502_14@
  const@H_502_14@ Hello = hello;
  return@H_502_14@ <Hello@H_502_14@ toWhat@H_502_14@="World"@H_502_14@ />@H_502_14@;@H_502_14@
}

4.正确的选择基于同一架构的不同组件

不要试图用表达式来构造JSX组件标签,如下

const@H_502_14@ components = {
  photo: PhotoStory,video: VideoStory
};

function@H_502_14@ Story@H_502_14@(props)@H_502_14@ {@H_502_14@
  return@H_502_14@ <components[props.storyType]@H_502_14@ story@H_502_14@={props.story}@H_502_14@ />@H_502_14@;@H_502_14@
}

方法会报错,解决的方案是,将这哥值赋值给一个大写开头的变量即可。

const@H_502_14@ components = {
  photo: PhotoStory,video: VideoStory
};
function@H_502_14@ Story@H_502_14@(props)@H_502_14@ {@H_502_14@
  // 如果没有此行报错@H_502_14@
  const@H_502_14@ SpecificStory = components[props.storyType];
  return@H_502_14@ <SpecificStory@H_502_14@ story@H_502_14@={props.story}@H_502_14@ />@H_502_14@;@H_502_14@
}

这里还需要注意的是,对于组件的名字是必须不同的,但是可以用相同的变量来处理,因为变量只是承载组件的容器而已,它作用只是为了让React可以将JSX语句变为一个对象。

function@H_502_14@ Story2@H_502_14@(props)@H_502_14@ {@H_502_14@
  return@H_502_14@ <div@H_502_14@>@H_502_14@22222222222</div@H_502_14@>@H_502_14@;@H_502_14@
}
function@H_502_14@ Story@H_502_14@(props)@H_502_14@ {@H_502_14@
  return@H_502_14@ <div@H_502_14@>@H_502_14@11111111111</div@H_502_14@>@H_502_14@;@H_502_14@
}
let@H_502_14@ Str = Story2;
ReactDOM.render(
    <Str@H_502_14@ />@H_502_14@,document.getElementById('example') ); Str = Story; ReactDOM.render( <Str@H_502_14@ />@H_502_14@,document.getElementById('example1') );@H_502_14@

5.JSXprops的多种运用

【这里介绍的内容有一部分在第一篇博客就讲到了】

javascript表达式

<MyComponent foo={1@H_502_14@ + 2@H_502_14@ + 3@H_502_14@ + 4@H_502_14@} />

字符串字面量

<MyComponent message="hello world"@H_502_14@ />

<MyComponent@H_502_14@ message@H_502_14@={'hello@H_502_14@ world@H_502_14@'} />@H_502_14@@H_502_14@

由于字符串处理的时候,React自动将字符串进行转义处理,所以下面两个语句是等价的。

<MyComponent message="&lt;3"@H_502_14@ />

<MyComponent@H_502_14@ message@H_502_14@={'<3'}@H_502_14@ />@H_502_14@@H_502_14@

属性的默认值

当你设定一个属性但是没有为他设置一个值的话,它的默认值会是 true.

<MyTextBox autocomplete />

<MyTextBox@H_502_14@ autocomplete@H_502_14@={true}@H_502_14@ />@H_502_14@@H_502_14@

两者是等价的,当然强烈要求不要这么做,如果有属性一定要赋初始值,因为这有可能和ES6的新对象特性相混淆。

ES6{autocomplete}表示的是{autocomplete : autocomplete}而不是{autocomplete:true},所以请使用第二种方式

6.扩展运算符

如果你有一个对象,想将它完整的传递给JSX作为JSXprops属性对象时,你可以使用...扩展运算符

function@H_502_14@ App1@H_502_14@()@H_502_14@ {@H_502_14@
  return@H_502_14@ <Greeting@H_502_14@ firstName@H_502_14@="Ben"@H_502_14@ lastName@H_502_14@="Hector"@H_502_14@ />@H_502_14@;@H_502_14@
}
function@H_502_14@ App2@H_502_14@()@H_502_14@ {@H_502_14@
  const@H_502_14@ props = {firstName: 'Ben'@H_502_14@,lastName: 'Hector'@H_502_14@};
  return@H_502_14@ <Greeting@H_502_14@ {...props@H_502_14@} />@H_502_14@;@H_502_14@
}

上述的第二个函数式组件的操作就相当于将props赋值给了App2.props属性

扩展运算符是ES6的新特性,它的作用基本和我们for in有点类似,遍历一个对象将它的所有属性提取出来。

当然在这里的运用,官方建议尽可能少用这种方式给JSX语句对象props属性赋值,因为会造成很多空间浪费,因为你可能有很多属性都不会用到。

7.JSXchildren属性

当我们增加内容给一个组件时,就相当于将内容增加到这个组件的children属性中,一般有以下几种应用方式。

字符串字面量

我们可以在组件之间增加字符串字面量,当然这个字面量可以是HTML语句,但是需要注意一点的是,这里的字符串字面量是没有被编码的,也就是说,当我们通过大括号进行表达式插入时,默认是进行编码的,而你自己增加内容是不会被编码的,所以在这里我们可以像在HTML中用标签一样在这里用,比如空格的话我们就需要用&amp;才能真的隔离开字符串

<div@H_502_14@>This is@H_502_14@ valid HTML &amp; JSX at@H_502_14@ the@H_502_14@ same time@H_502_14@.</div@H_502_14@>

这样的原因是,JSX自动删除空格符,换行符,等等。

<div>Hello World</div> <div> Hello World </@H_502_14@div>

<div@H_502_14@>@H_502_14@ Hello World </div@H_502_14@>@H_502_14@ <div@H_502_14@>@H_502_14@ Hello World </div@H_502_14@>@H_502_14@@H_502_14@

上述的四种情况的最终视图呈现结果是一样

JSX作为孩子

JSX语句对象又作为孩子

<MyContainer@H_502_14@>@H_502_14@
  <MyFirstComponent@H_502_14@ />@H_502_14@
  <MySecondComponent@H_502_14@ />@H_502_14@
</MyContainer@H_502_14@>@H_502_14@

我们可以在组件中混用HTMLJSXReact自动的处理,区分

javascript表达式

首先可以明确地是任何javascript表达式只要放在大括号中都可以在JSX中使用,毫无障碍,所以放在孩子中是没有一点问题的。

甚至我们可以直接将一个数组输出到我们的JSX

function@H_502_14@ Item@H_502_14@(props)@H_502_14@ {@H_502_14@
  return@H_502_14@ <li@H_502_14@>@H_502_14@{props.message}</li@H_502_14@>@H_502_14@;@H_502_14@
}

function@H_502_14@ TodoList@H_502_14@()@H_502_14@ {@H_502_14@
  const@H_502_14@ todos = ['finish doc'@H_502_14@,'submit pr'@H_502_14@,'nag dan to review'@H_502_14@];
  return@H_502_14@ (
    <ul@H_502_14@>@H_502_14@ {todos.map((message) => <Item@H_502_14@ key@H_502_14@={message}@H_502_14@ message@H_502_14@={message}@H_502_14@ />@H_502_14@)} </ul@H_502_14@>@H_502_14@ ); }@H_502_14@

函数也是个孩子

可以是匿名函数,也可以是箭头函数

function@H_502_14@ Repeat@H_502_14@(props)@H_502_14@ {@H_502_14@
  let@H_502_14@ items = [];
  for@H_502_14@ (let@H_502_14@ i = 0@H_502_14@; i < props.numTimes; i++) {
    items.push(props.children(i));
  }
  return@H_502_14@ <div@H_502_14@>@H_502_14@{items}</div@H_502_14@>@H_502_14@;@H_502_14@
}

function@H_502_14@ ListOfTenThings@H_502_14@()@H_502_14@ {@H_502_14@
  return@H_502_14@ (
    <Repeat@H_502_14@ numTimes@H_502_14@={10}@H_502_14@>@H_502_14@ {(index) => <div@H_502_14@ key@H_502_14@={index}@H_502_14@>@H_502_14@This is item {index} in the list</div@H_502_14@>@H_502_14@} </Repeat@H_502_14@>@H_502_14@ ); }@H_502_14@

8.Booleans,Null,和Undefined是无用的

false,null,undefined,和 true虽然用大括号括起来是一个合法的孩子,但是他们不会被呈现在视图中

<div />

<div@H_502_14@>@H_502_14@</div@H_502_14@>@H_502_14@ <div@H_502_14@>@H_502_14@{false}</div@H_502_14@>@H_502_14@ <div@H_502_14@>@H_502_14@{null}</div@H_502_14@>@H_502_14@ <div@H_502_14@>@H_502_14@{undefined}</div@H_502_14@>@H_502_14@ <div@H_502_14@>@H_502_14@{true}</div@H_502_14@>@H_502_14@@H_502_14@

这些代码都是等价的。

既然不会显示,那么留着这个有个毛线用,当然是有用的,我们可以通过这些东西来选择性的输出数据给视图显示

<div>
  {showHeader && <Header@H_502_14@ />@H_502_14@} <Content@H_502_14@ />@H_502_14@ </div@H_502_14@>@H_502_14@ @H_502_14@

因为showHeaderfalse的时候不会将这一行的数据显示出来,而为true的时候则会显示<Head />内容

当然如果是一些特殊的转换判断就得另算了,比如说01他们会被判断为falsetrue,但是会显示出来。

<div>
  {props.messages.length &&
    <MessageList@H_502_14@ messages@H_502_14@={props.messages}@H_502_14@ />@H_502_14@ } </div@H_502_14@>@H_502_14@@H_502_14@

这里props.messages.length等于0的话,会显示出一个0,所以我们使用时一定要将它变为一个布尔表达式

<div>
  {props.messages.length > 0@H_502_14@ &&
    <MessageList@H_502_14@ messages@H_502_14@={props.messages}@H_502_14@ />@H_502_14@ } </div@H_502_14@>@H_502_14@@H_502_14@

当然如果你想输出这几个单词的话,对不起了,只能转换为字符串输出

<div@H_502_14@>
  My JavaScript variable@H_502_14@ is {String(myVariable)}.
</div@H_502_14@>

下一篇将讲React中的类型检查

猜你在找的React相关文章