Build a Recipe Box

React Project (三)

A Recipe Box

目标: 在 CodePen.io 上创建一个这样的应用,它的功能类似于这个 http://codepen.io/FreeCodeCamp/full/qbqqJm/

功能:当我填入名字和食材,我就能够创建一个食谱。

功能:我能看见我需要的食谱的列表,能点进去查看食谱,能编辑食谱,能删除食谱。

功能:所有的食谱,都应该存储在本地。当我刷新页面时,我添加的食谱不会丢失。

camper

项目链接

此项目为freeCodeCamp中React的第三个实践项目。重点包括使用React-Bootstrap组件库,本地存储window.localStorage,包括控件重绘requestAnimationFrame()等。

项目代码:

<!DOCTYPE html>
<!DOCTYPE html>
var Panel = ReactBootstrap.Panel, Accordion = ReactBootstrap.Accordion;
var ListGroup = ReactBootstrap.ListGroup,ListGroupItem = ReactBootstrap.ListGroupItem;
var Button = ReactBootstrap.Button, ButtonToolbar = ReactBootstrap.ButtonToolbar;
var Modal = ReactBootstrap.Modal;
var form = ReactBootstrap.form, Input = ReactBootstrap.Input;
var FormGroup = ReactBootstrap.FormGroup, ControlLabel = ReactBootstrap.ControlLabel;
var FormControl = ReactBootstrap.FormControl;

var storage = window.localStorage;
storage["recipeBook"] = '[{"title":"锅包肉", "ingredients":["猪里脊肉300克", "土豆淀粉150克", "白糖100克", "醋100克", "酱油,盐,葱,姜,蒜,香菜适量"]}, {"title":"肉段烧茄子", "ingredients":["猪肉",  "淀粉", "茄子", "鸡蛋清", "尖椒", "糖,酱油,盐,葱,姜,蒜适量"]}, {"title":"猪肉炖粉条", "ingredients":["重点:肥肉多一些的五花肉", "粉条", "自家酸菜", "盐,葱姜蒜,桂皮,生抽,老抽,花椒大料适量"]}]';

var recipes = JSON.parse(storage["recipeBook"]);
var globalTitle = "", globalIngredients = [], editKey = -1;

var IngredientList = React.createClass({
  render: function(){
    var ingredientList = this.props.ingredients.map(function(ingredient){
      return (
        <ListGroupItem>
                {ingredient}
            </ListGroupItem>
          );
    });
    return (
      <ListGroup>
        {ingredientList}
      </ListGroup>
    );
  }
});


var Recipe = React.createClass({
  remove: function() {
    recipes.splice(this.props.index, 1);
    ReactDOM.render(<RecipeBook recipebook={recipes} />, document.getElementById("container"));   
  },
  edit: function() {
      globalTitle = this.props.title;
      globalIngredients = this.props.ingredients;
      editKey = this.props.index;
      document.getElementById("add").click();

    },
  render: function() {
    return (
      <div>
        <h4 className="text-center">材料</h4> <hr />
        <IngredientList ingredients = {this.props.ingredients} />
        <ButtonToolbar>
                <Button bsStyle="danger" id={"btn-del"+this.props.index} onClick={this.remove}>删除</Button>
                <Button bsStyle="default" id={"btn-edit"+this.props.index} onClick={this.edit}>修改</Button>
            </ButtonToolbar>
          </div>
    );
  }
});

var RecipeBook = React.createClass({
  render: function() {
    var recipeBooks = this.props.recipebook.map(function(recipeindex, i){
      return (
        <Panel header={recipeindex.title} eventKey={i} bsStyle="success">
              <Recipe title={recipeindex.title} ingredients={recipeindex.ingredients} index={i}/>
          </Panel>
      );
    });
    return (
    <div>
      <Accordion>
        {recipeBooks}
      </Accordion>

    </div>
    );
  }
});

var ModalAdd = React.createClass({
  getInitialState() {
      return { 
        showModal: false
       };
    },
    componentDidMount: function() {
    $("#add").hide();
    },
  close: function() {
    globalTitle = "";
      globalIngredients = [];
    this.setState({ showModal: false });
  },
  open: function() {
    this.setState({ showModal: true });
    if(document.getElementById("newName") && document.getElementById("newIngredients")) {
      document.getElementById("newName").value = globalTitle;
          document.getElementById("newIngredients").value = globalIngredients.join(",");
          if (globalTitle != "") {
            $("#modalTitle").text("修改菜品");
          }
    }
    else requestAnimationFrame(this.open);
  },
  save: function() {
    var newTitle = document.getElementById("newName").value;
    var newIngredients = document.getElementById("newIngredients").value.split(",");
    var newRecipes = recipes;
    if(editKey != -1) {
      newRecipes[editKey] = {title: newTitle, ingredients: newIngredients};
    } else {
      if(newTitle.length < 1) {
        newTitle = "未命名"
      }   
      newRecipes.push({title: newTitle, ingredients: newIngredients})
    }

    storage["recipeBook"] = newRecipes;
    ReactDOM.render(<RecipeBook recipebook={recipes} />, document.getElementById("container"));
    this.close();

  },
  add: function() {
    editKey = -1;
    this.open();
  },
  render: function() {
    return (
    <div>
      <Button onClick={this.open} id="add"></Button>
      <Button bsStyle="primary" bsSize="large" onClick={this.add} id="show">新增</Button>
          <Modal show={this.state.showModal} onHide={this.close}>
            <Modal.Header>
              <Modal.Title id="modalTitle">添加菜品</Modal.Title>
              </Modal.Header>
              <Modal.Body>
                <form>
                  <FormGroup>
                      <ControlLabel>菜名:</ControlLabel>
                      <FormControl componentClass="input" type="text" id="newName" placeholder="瞎填点啥呗。。"/>
                  </FormGroup>
                  <FormGroup>
                      <ControlLabel>所需材料:</ControlLabel>
                      <FormControl componentClass="textarea" id="newIngredients"></FormControl>
                  </FormGroup>
                </form>
              </Modal.Body> 
              <Modal.Footer>
                <Button bsStyle="primary" id="addButton" onClick={this.save}>保存</Button>
                <Button bsStyle="default" onClick={this.close}>退出</Button>
              </Modal.Footer>
          </Modal>
        </div>
    );
  }
});

ReactDOM.render(<RecipeBook recipebook={recipes} />, document.getElementById("container"));

ReactDOM.render(<ModalAdd />, document.getElementById("button"));

All Javascript Project

WEB
React project