首页 > 专栏 > 前端 > 文章详情
用 React 描述一幅 UI,并实时更新数据列表 发布于:2021-03-24 13:48:59   来源:React   查看:3  讨论:0
第一次写:
class FilterableProductTable1 extends React.Component{
  constructor (props) {
    super(props);
    this.state = {
      productCategoryRow: data7.title,
      productName: data1.name,
      productPrice: data1.price
    }
  }
  render () {
    return(
        <div className="FilterProductTable">
          <SearchBar/>
          <ProductTable
              productCategoryRow={this.state.productCategoryRow}
              productName={this.state.productName} productPrice={this.state.productPrice}
          />
        </div>
    )
  }
}
class SearchBar extends React.Component{
  constructor (props) {super(props);}
  render () {
    return(
        <div className="SearchBar">
          <form>
            <input type="text" placeholder="Search..."/>
            <label className="label">
              <input type="checkbox" value="false"/>Only show products is stock.
            </label>
          </form>
        </div>
    )
  }
}
class ProductTable extends React.Component{
  constructor (props) {super(props);}
  render () {
    return(
        <div className="ProductTable">
          <ProductCategoryRow productCategoryRow={this.props.productCategoryRow}/>
          <ProductRow productName={this.props.productName} productPrice={this.props.productPrice}/>
        </div>
    )
  }
}
class ProductCategoryRow extends React.Component{
  constructor (props) {super(props);}
  render () {
    return(
        <h2>{this.props.productCategoryRow}</h2>
    )
  }
}
class ProductRow extends React.Component{
  constructor (props) {super(props);}
  render () {
    return(
        <ul>
          <li>
            <span>{this.props.productName}</span>
            <em>{this.props.productPrice}</em>
          </li>
        </ul>
    )
  }
}
class ProductData {
  constructor (category, price, stocked, name) {
    this.category = category;
    this.price = price;
    this.stocked = stocked;
    this.name = name;
  }
}
class TitleData {
  constructor (title) {
    this.title = title;
  }
}
const data1 = new ProductData('Sporting Goods', '$49.99', 'true', 'Football');
const data2 = new ProductData('Sporting Goods', '$9.99', 'true', 'Baseball');
const data3 = new ProductData('Sporting Goods', '$29.99', 'false', 'Basketball');
const data4 = new ProductData('Electronics', '$99.99', 'true', 'iPod Touch');
const data5 = new ProductData('Electronics', '$399.99', 'false', 'iPhone 5');
const data6 = new ProductData('Electronics', '$199.99', 'true', 'Nexus 7');
const data7 = new TitleData('Sporting Goods');
const data8 = new TitleData('Electronics');
//React方式构建渲染UI
export default FilterableProductTable1;
总结:cMI易塔云建站-模板下载,web开发资源,技术博客
遇到父子组件不很少,一般写法固定从子组件往上写,顺序方便一些。cMI易塔云建站-模板下载,web开发资源,技术博客
不是每一个class组件都要写constructor,如果数据是来源于自己,那就再写不迟。cMI易塔云建站-模板下载,web开发资源,技术博客
在render开始时,首先把需要用到的属性变量声明一下,养成良好习惯。
render () {
  const item = this.props.item;
  const price = this.props.price;
  return(
因为开发环境是在react下,所以在任何return后面直接HTML语句都不应该报错,不要用旧习惯再写单引号了。cMI易塔云建站-模板下载,web开发资源,技术博客
数据处理,可以直接把数组或者对象直接当做JSX语法标签的一个属性带进去,不需要之前把数据排布好,没必要。cMI易塔云建站-模板下载,web开发资源,技术博客
哪里用到数组的值,再在那里用数组方法把数据取出来即可。其实并没有把方法抽离。全程是带着大数组进去渲染的。
cMI易塔云建站-模板下载,web开发资源,技术博客
cMI易塔云建站-模板下载,web开发资源,技术博客
第二次写:
class ProductCategoryRow extends React.Component{
  // Before constructor (props) {super(props);} //什么内部属性都没用,那就不用写
  render () {
    const category = this.props.category;
    return(
        <h2>{category}</h2>
    )
  }
}
class ProductRow extends React.Component{
  render () {
    const item = this.props.item;
    const price = this.props.price;
    return(
        <li>
          <span>{item}</span>
          <em>{price}</em>
        </li>
    )
  }
}
class SearchBar extends React.Component{
  render () {
    const filterText = this.props.filterText;
    const inStockOnly = this.props.inStockOnly;
    return(
        <form>
          <input type="text" placeholder="Search..." defaultValue={filterText}/>
          <label className="label">
            <input type="checkbox" defaultChecked={inStockOnly} />Only show products is stock.
          </label>
        </form>
    )
  }
}
class ProductTable extends React.Component{
  render () {
    const filterText = this.props.filterText;
    const inStockOnly = this.props.inStockOnly;
    const rows = [];
    const productLists = this.props.products;
    let lastCategory = null;
    productLists.forEach(
        (item,i) => {
          if (item.name.indexOf(filterText) === -1) {
            return;
          }
          if (inStockOnly && !item.stocked) {
            return;
          };
          if(item.category !== lastCategory){
            rows.push(
                <ProductCategoryRow key={item.category} category={item.category}/>
            )
          };
          rows.push(
              <ProductRow item={item.name} price={item.price} key={i}/>
          );
          lastCategory = item.category;
        }
    )
    return(
        <div>
          <ul>
            {/*因为rows上面返回的是虚拟机DOM,所以可以直接在JSX里渲染了。*/}
            {rows}
          </ul>
        </div>
    )
  }
}
class FilterableProductTable3 extends React.Component{
  constructor (props) {
    super(props);
    this.state = {
      filterText : 'ball',
      inStockOnly : true
    }
  }
  render () {
    return(
        <div>
          <SearchBar filterText={this.state.filterText} inStockOnly={this.state.inStockOnly}/>
          <table width="377" >
            <tbody>
            <tr>
              <td align="middle" valign="middle">Names</td>
              <td align="middle" valign="middle">Prices</td>
            </tr>
            </tbody>
          </table>
          <ProductTable products={PRODUCTS} filterText={this.state.filterText} inStockOnly={this.state.inStockOnly}/>
        </div>
    )
  }
}
const PRODUCTS = [
  {category: 'Sporting Goods', price: '$49.99', stocked: true, name: 'Football'},
  {category: 'Sporting Goods', price: '$9.99', stocked: true, name: 'Baseball'},
  {category: 'Sporting Goods', price: '$29.99', stocked: false, name: 'Basketball'},
  {category: 'Electronics', price: '$99.99', stocked: true, name: 'iPod Touch'},
  {category: 'Electronics', price: '$399.99', stocked: false, name: 'iPhone 5'},
  {category: 'Electronics', price: '$199.99', stocked: true, name: 'Nexus 7'}
];
确定state存放的为止。cMI易塔云建站-模板下载,web开发资源,技术博客
    注意:React中的数据流是单向的,并随着组件层级从上往下传递。cMI易塔云建站-模板下载,web开发资源,技术博客
    判断方法:cMI易塔云建站-模板下载,web开发资源,技术博客
        1、找到根据这个state进行渲染的所有组件。cMI易塔云建站-模板下载,web开发资源,技术博客
        2、找到他们的共同所有者(common owner)组件(差不多类似于父组件)cMI易塔云建站-模板下载,web开发资源,技术博客
        3、该共同所有者组件或者比它层级更高的组件应该拥有state。cMI易塔云建站-模板下载,web开发资源,技术博客
        4、如果是找不到合适的位置来存放state,就直接创建一个,并将该组件置于高于共同所有者组件层级的位置。cMI易塔云建站-模板下载,web开发资源,技术博客
    我们考虑:cMI易塔云建站-模板下载,web开发资源,技术博客
        1、ProductTable 需要根据state删选产品列表。SearchBar需要展示搜索词和复选框的状态。cMI易塔云建站-模板下载,web开发资源,技术博客
        2、他们的共同所有者是FilterableProductTable。cMI易塔云建站-模板下载,web开发资源,技术博客
        3、因此,搜索词和复选框的值应该很自然地存放在FilterableProductTable组建中。cMI易塔云建站-模板下载,web开发资源,技术博客
    now,我们已经决定把这些state存放在FilterableProductTable中。cMI易塔云建站-模板下载,web开发资源,技术博客
        首先,将实例属性 this.state={filterText='', inStockOnly: false}添加到constructor中。cMI易塔云建站-模板下载,web开发资源,技术博客
        然后,将filterText和inStockOnly作为props传入ProductTable和SearchBar。cMI易塔云建站-模板下载,web开发资源,技术博客
        最后,用这些props筛选ProductTable中的产品信息,并设置SearchBar的表单值。
class ProductCategoryRow extends React.Component{
  // Before constructor (props) {super(props);} //什么内部属性都没用,那就不用写
  render () {
    const category = this.props.category;
    return(
        <h2>{category}</h2>
    )
  }
}
class ProductRow extends React.Component{
  render () {
    const item = this.props.item;
    const price = this.props.price;
    return(
        <li>
          <span>{item}</span>
          <em>{price}</em>
        </li>
    )
  }
}
class ProductTable extends React.Component{
  render () {
    const filterText = this.props.filterText;
    const inStockOnly = this.props.inStockOnly;
    const rows = [];
    const productLists = this.props.products;
    let lastCategory = null;
    productLists.forEach(
        (item,i) => {
          if (item.name.indexOf(filterText) === -1) {
            return;
          }
          if (inStockOnly && !item.stocked) {
            return;
          };
          if(item.category !== lastCategory){
            rows.push(
                <ProductCategoryRow key={item.category} category={item.category}/>
            )
          };
          rows.push(
              <ProductRow item={item.name} price={item.price} key={i}/>
          );
          lastCategory = item.category;
        }
    )
    return(
        <div>
          <ul>
            {/*因为rows上面返回的是虚拟机DOM,所以可以直接在JSX里渲染了。*/}
            {rows}
          </ul>
        </div>
    )
  }
}
class SearchBar extends React.Component{
  constructor (props) {
    super(props);
    this.zhishiyonglaizhixingeryi = this.zhishiyonglaizhixingeryi.bind(this);
    this.checkedChange = this.checkedChange.bind(this);
  }
  zhishiyonglaizhixingeryi(e) { //只是用来执行一条语句而已,叫什么名字无所谓,目的用于:给外部父组件的属性:onFilterTextChange,传入一个值
    this.props.onFilterTextChange(e.target.value);
    // console.log(this.props.onFilterTextChange);  //打印出来是一个函数
  }
  checkedChange(e){
    this.props.onInStockOnlyChnage(e.target.checked);
  }
  render () {
    const filterText = this.props.filterText;
    const inStockOnly = this.props.inStockOnly;
    return(
        <form>
          <input type="text" placeholder="Search..." defaultValue={filterText} onChange={this.zhishiyonglaizhixingeryi}/>
          <label className="label">
            <input type="checkbox" defaultChecked={inStockOnly} onChange={this.checkedChange}/>Only show products is stock.
          </label>
        </form>
    )
  }
}
class FilterableProductTable4 extends React.Component{
  constructor (props) {
    super(props);
    this.state = {
      filterText : '',
      inStockOnly : false
    };
    this.handleFilterTextChange = this.handleFilterTextChange.bind(this);
    this.handleInStockOnlyChange = this.handleInStockOnlyChange.bind(this);
  }
  handleFilterTextChange(ahsasfasf){  //ahsasfasf 只是一个外参,叫什么名字都无所谓,是内部组件zhishiyonglaizhixingeryi方法执行的
    return this.setState({filterText: ahsasfasf})
  }
  handleInStockOnlyChange(hahahaha){
    this.setState({inStockOnly: hahahaha})
  }
  render () {
    return(
        <div>
          <SearchBar
              filterText={this.state.filterText}
              inStockOnly={this.state.inStockOnly}
              onFilterTextChange={this.handleFilterTextChange}
              onInStockOnlyChnage={this.handleInStockOnlyChange}
          />
          <table width="377" >
            <tbody>
            <tr>
              <td align="middle" valign="middle">Names</td>
              <td align="middle" valign="middle">Prices</td>
            </tr>
            </tbody>
          </table>
          <ProductTable products={PRODUCTS} filterText={this.state.filterText} inStockOnly={this.state.inStockOnly}/>
        </div>
    )
  }
}
const PRODUCTS = [
  {category: 'Sporting Goods', price: '$49.99', stocked: true, name: 'Football'},
  {category: 'Sporting Goods', price: '$9.99', stocked: true, name: 'Baseball'},
  {category: 'Sporting Goods', price: '$29.99', stocked: false, name: 'Basketball'},
  {category: 'Electronics', price: '$99.99', stocked: true, name: 'iPod Touch'},
  {category: 'Electronics', price: '$399.99', stocked: false, name: 'iPhone 5'},
  {category: 'Electronics', price: '$199.99', stocked: true, name: 'Nexus 7'}
];
//React方式构建渲染UI
export default FilterableProductTable4;
添加反向数据流。cMI易塔云建站-模板下载,web开发资源,技术博客
    到目前为止,我们已经借助自上而下传递的props和state渲染了一个应用。现在我们将尝试cMI易塔云建站-模板下载,web开发资源,技术博客
    让数据反向传递:处于较低层次的表单组件更新较高层级的FilterableProductTable中的state。cMI易塔云建站-模板下载,web开发资源,技术博客
    cMI易塔云建站-模板下载,web开发资源,技术博客
    React通过一种比传统的双向绑定略微繁琐的方法来实现反向数据传递。有助于理解程序的运作方式。cMI易塔云建站-模板下载,web开发资源,技术博客
    cMI易塔云建站-模板下载,web开发资源,技术博客
    如果你现在就搜索框输入值或勾选复选框,React不会产生任何反应。这是正常的,因为我们已经将cMI易塔云建站-模板下载,web开发资源,技术博客
    input的值设置为了从FilterableProductTable传递而来的固定值。cMI易塔云建站-模板下载,web开发资源,技术博客
    cMI易塔云建站-模板下载,web开发资源,技术博客
    让我们来梳理一下需要实现的功能:cMI易塔云建站-模板下载,web开发资源,技术博客
        1、每当用户改变表单值,我们需要改变state来反应用户的当前输入。cMI易塔云建站-模板下载,web开发资源,技术博客
        2、由于state只能由拥有它们的组件进行更改,FilterableProductTable必须将一个能触发cMI易塔云建站-模板下载,web开发资源,技术博客
            state改变的回调函数传递给SearchBar。cMI易塔云建站-模板下载,web开发资源,技术博客
        3、我们可以使用输入框的onChange事件来监视用户输入的变化,并通知父组件FilterableProductTablecMI易塔云建站-模板下载,web开发资源,技术博客
            传递给SearchBar的那个函数(那是一个回调函数callback)。cMI易塔云建站-模板下载,web开发资源,技术博客
        4、然后,该回调函数将更新state
cMI易塔云建站-模板下载,web开发资源,技术博客
cMI易塔云建站-模板下载,web开发资源,技术博客
□,默认状态。cMI易塔云建站-模板下载,web开发资源,技术博客
cMI易塔云建站-模板下载,web开发资源,技术博客
□,输入a。cMI易塔云建站-模板下载,web开发资源,技术博客
cMI易塔云建站-模板下载,web开发资源,技术博客
cMI易塔云建站-模板下载,web开发资源,技术博客
□,勾选复选框。cMI易塔云建站-模板下载,web开发资源,技术博客
cMI易塔云建站-模板下载,web开发资源,技术博客

评论

  • 匿名