首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >星舰比较应用程序与ES6生成器和星球大战API

星舰比较应用程序与ES6生成器和星球大战API
EN

Code Review用户
提问于 2017-11-19 13:35:58
回答 1查看 150关注 0票数 6

赋值描述:

制作一个基于星球大战API的比较星舰的web应用程序。

应包括:

  • 标签“从下拉列表中选择两艘星舰进行比较”。
  • 两个下拉式控制装置装满了星际飞船。
  • 按钮“比较”。
  • 显示规格(速度、货物、成本等)的表格两艘星际飞船。

当用户单击“比较”按钮时,表将被填充。基于在昏睡控制中选择的选项。

在每一行:高亮显示值较高的单元格。

代码语言:javascript
运行
复制
(() => { 
    function removeHigherValueClass() {
        document.querySelectorAll('.data-cell').forEach((dataCell) => {
            dataCell.classList.remove('higher-value');
        });
    }

    function runGen() {
        let genObj = gen();

        function nextItem(obj) {
            if (obj.done) {
                return obj.value;
            }
            // As long as there a further yield
            //  statements in the generator function ...
            obj.value.then((value) => {
                nextItem(genObj.next(value));
            }).catch((error) => {
                console.log(error);
            });    
        }

        nextItem(genObj.next()); // Trigger the recursion the first time.
    }

    function* gen() {  
        let url = 'https://swapi.co/api/starships/';
        let dataCells = document.querySelectorAll('.data-cell');
        let json = [];

        let oneResponse = yield fetch(
            url + document.getElementById('starShipOne').value, 
            { mode: 'cors' } );
        json.push(yield oneResponse.json());

        let twoResponse = yield fetch(
            url + document.getElementById('starShipTwo').value, 
            { mode: 'cors' } );
        json.push(yield twoResponse.json());

        dataCells.forEach((dataCell) => {
            let key = dataCell.dataset.key; // The more general name ...

            // Starship One == 0, Starship Two == 1
            for (let i = 0; i < 2; i++) {
                document.getElementById(key + i).textContent = json[i][key]; // The general name together with the index gives the concrete ID.
            }

            if (!isNaN(json[0][key])) { // If it is computable, comparable data ...

                if (parseFloat(json[0][key]) > parseFloat(json[1][key])) { // ... then compare the current spec. Class has only to be attached if one value is really higher. No attachment when equal.
                    document.getElementById(key + 0)
                            .classList.add('higher-value');
                } else if (parseFloat(json[1][key]) > parseFloat(json[0][key])) {
                    document.getElementById(key + 1)
                            .classList.add('higher-value');
                }

            }
        });
    }   

    document
        .getElementById('compare')
        .addEventListener('click', () => {
            removeHigherValueClass();
            runGen();
        });
})();
代码语言:javascript
运行
复制
html {
            background-color: rgba(245, 245, 245, .5);
        }

        .higher-value {
            background-color: pink;
            font-weight: 900;
        }

        .main-wrap {
            max-width: 800px;
            margin: 40px auto;
        }

        .main-nav {
            margin: 0 0 30px;
        }

        .data-cell {
            text-align: center;
            width: 200px;
        }
代码语言:javascript
运行
复制
<section>
        <div class="main-wrap">
            <h3>Select two Starships from the dropdown lists to compare</h3>
            <nav class="main-nav">
                <select id="starShipOne">
                    <option value="2" selected="selected">CR90 Corvette</option>
                    <option value="75">V-wing</option>
                    <option value="74">Belbullab-22 Starfighter</option>
                    <option value="65">Jedi Interceptor</option>

                    <option value="3">Star Destroyer</option>
                    <option value="59">Trade Fedaration Cruiser</option>
                    <option value="58">Solar Sailer</option>
                    <option value="63">Republic Attack Cruiser</option>

                    <option value="28">A-wing</option>
                    <option value="29">B-wing</option>
                    <option value="39">Naboo Fighter</option>
                    <option value="10">Millenium Falcon</option>
                </select>
                <select id="starShipTwo">
                    <option value="2">CR90 Corvette</option>
                    <option value="75" selected="selected">V-wing</option>
                    <option value="74">Belbullab-22 Starfighter</option>
                    <option value="65">Jedi Interceptor</option>

                    <option value="3">Star Destroyer</option>
                    <option value="59">Trade Fedaration Cruiser</option>
                    <option value="58">Solar Sailer</option>
                    <option value="63">Republic Attack Cruiser</option>

                    <option value="28">A-wing</option>
                    <option value="29">B-wing</option>
                    <option value="39">Naboo Fighter</option>
                    <option value="10">Millenium Falcon</option>
                </select>
                <button id="compare">Compare</button>
            </nav>
            <table border="1">
                <tr>
                    <th></th>
                    <th>Starship 1</th>
                    <th>Starship 2</th>
                </tr>
                <tr>
                    <td>Name</td>
                    <!-- 'data-key' will later determine the row. 
                         id='data-key-value[ 0 || 1 ]' determines the cell -->
                    <td class="data-cell" data-key="name" id="name0"></td>
                    <td class="data-cell" data-key="name" id="name1"></td>
                </tr>
                <tr>
                    <td>Cost</td>
                    <td class="data-cell" data-key="cost_in_credits" id="cost_in_credits0"></td>
                    <td class="data-cell" data-key="cost_in_credits" id="cost_in_credits1"></td>
                </tr>
                <tr>
                    <td>Speed</td>
                    <td class="data-cell" data-key="max_atmosphering_speed" id="max_atmosphering_speed0"></td>
                    <td class="data-cell" data-key="max_atmosphering_speed" id="max_atmosphering_speed1"></td>
                </tr>
                <tr>
                    <td>Cargo Size</td>
                    <td class="data-cell" data-key="cargo_capacity" id="cargo_capacity0"></td>
                    <td class="data-cell" data-key="cargo_capacity" id="cargo_capacity1"></td>
                </tr>
                <tr>
                    <td>Passengers</td>
                    <td class="data-cell" data-key="passengers" id="passengers0"></td>
                    <td class="data-cell" data-key="passengers" id="passengers1"></td>
                </tr>
            </table>
        </div>
    </section>

你认为我的想法是什么,一般的名称-属性和特定的ID?是否有更好的解决办法?那么依赖于HTML-属性是很好的实践吗?

你对总体上的实现有什么看法?

感谢所有提示、建议和评论。

EN

回答 1

Code Review用户

发布于 2018-11-21 23:17:59

我还注意到,可以用const而不是类似letkey来声明一些变量,因为在forEach回调中永远不会重新分配它。

代码语言:javascript
运行
复制
dataCells.forEach((dataCell) => {
  const key = dataCell.dataset.key; // The more general name ...

您可以将URL抽象到顶部,作为常量(或者在配置文件中)。这样,如果URL发生变化,您可以在一个地方完成,而不必将其与代码混在一起。

代码语言:javascript
运行
复制
const API_URL = 'https://swapi.co/api/starships/';

类似地,fetch()的选项可以存储在常量中。

代码语言:javascript
运行
复制
  const fetchOptions = {mode: 'cors'};

简化问题的另一个选择是使用Promise.all()同时运行两个API请求,然后从每个响应中获取JSON。

代码语言:javascript
运行
复制
const API_URL = 'https://swapi.co/api/starships/';
(() => {
  const dataCells = [...document.getElementsByClassName('data-cell')];
  const starShipOne = document.getElementById('starShipOne');
  const starShipTwo = document.getElementById('starShipTwo');

  function removeHigherValueClass() {
    dataCells.forEach((dataCell) => {
      dataCell.classList.remove('higher-value');
    });
  }
  const fetchOptions = {mode: 'cors'};
  function getData() {
    const oneResponse = fetch(API_URL + starShipOne.value, fetchOptions);

    const twoResponse = fetch(API_URL + starShipTwo.value, fetchOptions);
    return Promise.all([oneResponse, twoResponse]);
  }
  function getJSONFromResponses(responses) {
    return Promise.all(responses.map(response => response.json()));
  }
  function updateDOM(json) {
    dataCells.forEach((dataCell, i) => {
      const key = dataCell.dataset.key; // The more general name ...
      dataCell.textContent = json[i % 2][key];
      // Starship One == 0, Starship Two == 1
      if (!isNaN(json[0][key])) { // If it is computable, comparable data ...

        if (parseFloat(json[i % 2][key]) > parseFloat(json[(i + 1) % 2][key])) { // ... then compare the current spec. Class has only to be attached if one value is really higher. No attachment when equal.
          dataCell.classList.add('higher-value');
        }
      }
    });
  }

  document
    .getElementById('compare')
    .addEventListener('click', () => {
      removeHigherValueClass();
      getData().then(getJSONFromResponses).then(updateDOM);
    });
})();
代码语言:javascript
运行
复制
html {
  background-color: rgba(245, 245, 245, .5);
}

.higher-value {
  background-color: pink;
  font-weight: 900;
}

.main-wrap {
  max-width: 800px;
  margin: 40px auto;
}

.main-nav {
  margin: 0 0 30px;
}

.data-cell {
  text-align: center;
  width: 200px;
}
代码语言:javascript
运行
复制
<section>
  <div class="main-wrap">
    <h3>Select two Starships from the dropdown lists to compare</h3>
    <nav class="main-nav">
      <select id="starShipOne">
        <option value="2" selected="selected">CR90 Corvette</option>
        <option value="75">V-wing</option>
        <option value="74">Belbullab-22 Starfighter</option>
        <option value="65">Jedi Interceptor</option>

        <option value="3">Star Destroyer</option>
        <option value="59">Trade Fedaration Cruiser</option>
        <option value="58">Solar Sailer</option>
        <option value="63">Republic Attack Cruiser</option>

        <option value="28">A-wing</option>
        <option value="29">B-wing</option>
        <option value="39">Naboo Fighter</option>
        <option value="10">Millenium Falcon</option>
      </select>
      <select id="starShipTwo">
        <option value="2">CR90 Corvette</option>
        <option value="75" selected="selected">V-wing</option>
        <option value="74">Belbullab-22 Starfighter</option>
        <option value="65">Jedi Interceptor</option>

        <option value="3">Star Destroyer</option>
        <option value="59">Trade Fedaration Cruiser</option>
        <option value="58">Solar Sailer</option>
        <option value="63">Republic Attack Cruiser</option>

        <option value="28">A-wing</option>
        <option value="29">B-wing</option>
        <option value="39">Naboo Fighter</option>
        <option value="10">Millenium Falcon</option>
      </select>
      <button id="compare">Compare</button>
    </nav>
    <table border="1">
      <tr>
        <th></th>
        <th>Starship 1</th>
        <th>Starship 2</th>
      </tr>
      <tr>
        <td>Name</td>
        <!-- 'data-key' will later determine the row. 
                         id='data-key-value[ 0 || 1 ]' determines the cell -->
        <td class="data-cell" data-key="name" id="name0"></td>
        <td class="data-cell" data-key="name" id="name1"></td>
      </tr>
      <tr>
        <td>Cost</td>
        <td class="data-cell" data-key="cost_in_credits" id="cost_in_credits0"></td>
        <td class="data-cell" data-key="cost_in_credits" id="cost_in_credits1"></td>
      </tr>
      <tr>
        <td>Speed</td>
        <td class="data-cell" data-key="max_atmosphering_speed" id="max_atmosphering_speed0"></td>
        <td class="data-cell" data-key="max_atmosphering_speed" id="max_atmosphering_speed1"></td>
      </tr>
      <tr>
        <td>Cargo Size</td>
        <td class="data-cell" data-key="cargo_capacity" id="cargo_capacity0"></td>
        <td class="data-cell" data-key="cargo_capacity" id="cargo_capacity1"></td>
      </tr>
      <tr>
        <td>Passengers</td>
        <td class="data-cell" data-key="passengers" id="passengers0"></td>
        <td class="data-cell" data-key="passengers" id="passengers1"></td>
      </tr>
    </table>
  </div>
</section>

我知道这最初是用ecmascript-6标记的,但我已经了解了更多关于ecmascript-2017特性的信息,比如关键字awaitasync functions,在使用了它们之后,我会意识到,它们可以极大地简化这里的代码。例如,不必使用生成器函数,您可以使其成为一个常规函数(但前面有async关键字),只需在每个异步请求之前添加await

代码语言:javascript
运行
复制
async function getData() {
    const oneResponse = await fetch(API_URL + starShipOne.value, fetchOptions);
    const firstJSON = await oneResponse.json();

    const twoResponse = await fetch(API_URL + starShipTwo.value, fetchOptions);
    const secondJSON = await twoResponse.json();
    return [firstJSON, secondJSON];
}

然后就不需要在迭代器上调用.next()的代码了。相反,只需调用.then(updateDOM)

代码语言:javascript
运行
复制
getData().then(updateDOM);

请参阅使用这些更新重写的代码。

代码语言:javascript
运行
复制
const API_URL = 'https://swapi.co/api/starships/';
(() => {
  const dataCells = [...document.getElementsByClassName('data-cell')];
  const starShipOne = document.getElementById('starShipOne');
  const starShipTwo = document.getElementById('starShipTwo');

  function removeHigherValueClass() {
    dataCells.forEach((dataCell) => {
      dataCell.classList.remove('higher-value');
    });
  }
  const fetchOptions = {mode: 'cors'};
  async function getData() {
    const oneResponse = await fetch(API_URL + starShipOne.value, fetchOptions);
    const firstJSON = await oneResponse.json();

    const twoResponse = await fetch(API_URL + starShipTwo.value, fetchOptions);
    const secondJSON = await twoResponse.json();
    return [firstJSON, secondJSON];
  }
  function updateDOM(json) {
    dataCells.forEach((dataCell, i) => {
      const key = dataCell.dataset.key; // The more general name ...
      dataCell.textContent = json[i % 2][key];
      // Starship One == 0, Starship Two == 1
      if (!isNaN(json[0][key])) { // If it is computable, comparable data ...

        if (parseFloat(json[i % 2][key]) > parseFloat(json[(i + 1) % 2][key])) { // ... then compare the current spec. Class has only to be attached if one value is really higher. No attachment when equal.
          dataCell.classList.add('higher-value');
        }
      }
    });
  }

  document
    .getElementById('compare')
    .addEventListener('click', () => {
      removeHigherValueClass();
      getData().then(updateDOM);
    });
})();
代码语言:javascript
运行
复制
html {
  background-color: rgba(245, 245, 245, .5);
}

.higher-value {
  background-color: pink;
  font-weight: 900;
}

.main-wrap {
  max-width: 800px;
  margin: 40px auto;
}

.main-nav {
  margin: 0 0 30px;
}

.data-cell {
  text-align: center;
  width: 200px;
}
代码语言:javascript
运行
复制
<section>
  <div class="main-wrap">
    <h3>Select two Starships from the dropdown lists to compare</h3>
    <nav class="main-nav">
      <select id="starShipOne">
        <option value="2" selected="selected">CR90 Corvette</option>
        <option value="75">V-wing</option>
        <option value="74">Belbullab-22 Starfighter</option>
        <option value="65">Jedi Interceptor</option>

        <option value="3">Star Destroyer</option>
        <option value="59">Trade Fedaration Cruiser</option>
        <option value="58">Solar Sailer</option>
        <option value="63">Republic Attack Cruiser</option>

        <option value="28">A-wing</option>
        <option value="29">B-wing</option>
        <option value="39">Naboo Fighter</option>
        <option value="10">Millenium Falcon</option>
      </select>
      <select id="starShipTwo">
        <option value="2">CR90 Corvette</option>
        <option value="75" selected="selected">V-wing</option>
        <option value="74">Belbullab-22 Starfighter</option>
        <option value="65">Jedi Interceptor</option>

        <option value="3">Star Destroyer</option>
        <option value="59">Trade Fedaration Cruiser</option>
        <option value="58">Solar Sailer</option>
        <option value="63">Republic Attack Cruiser</option>

        <option value="28">A-wing</option>
        <option value="29">B-wing</option>
        <option value="39">Naboo Fighter</option>
        <option value="10">Millenium Falcon</option>
      </select>
      <button id="compare">Compare</button>
    </nav>
    <table border="1">
      <tr>
        <th></th>
        <th>Starship 1</th>
        <th>Starship 2</th>
      </tr>
      <tr>
        <td>Name</td>
        <!-- 'data-key' will later determine the row. 
                         id='data-key-value[ 0 || 1 ]' determines the cell -->
        <td class="data-cell" data-key="name" id="name0"></td>
        <td class="data-cell" data-key="name" id="name1"></td>
      </tr>
      <tr>
        <td>Cost</td>
        <td class="data-cell" data-key="cost_in_credits" id="cost_in_credits0"></td>
        <td class="data-cell" data-key="cost_in_credits" id="cost_in_credits1"></td>
      </tr>
      <tr>
        <td>Speed</td>
        <td class="data-cell" data-key="max_atmosphering_speed" id="max_atmosphering_speed0"></td>
        <td class="data-cell" data-key="max_atmosphering_speed" id="max_atmosphering_speed1"></td>
      </tr>
      <tr>
        <td>Cargo Size</td>
        <td class="data-cell" data-key="cargo_capacity" id="cargo_capacity0"></td>
        <td class="data-cell" data-key="cargo_capacity" id="cargo_capacity1"></td>
      </tr>
      <tr>
        <td>Passengers</td>
        <td class="data-cell" data-key="passengers" id="passengers0"></td>
        <td class="data-cell" data-key="passengers" id="passengers1"></td>
      </tr>
    </table>
  </div>
</section>
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/180798

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档