【问题标题】:How do I simplify this code? Is there a better way of doing this?如何简化此代码?有没有更好的方法来做到这一点?
【发布时间】:2019-07-01 01:49:25
【问题描述】:

经过数小时的压力,我才让这段代码正常工作。我是 Javascript 的新手,所以我不确定我是否以最有效的方式做到了这一点。我正在使用 IEX 提供的 API。此代码的目标是在有消息时输出消息。正如你所知道的,这并不完全有效,但我确实得到了标题。所以,如果我做错了什么,请告诉我。

<html>
<head>
    <style>
        /* Outter Table <Tbody> Settings*/
        .outtertable tbody {
            vertical-align: top;
        }

        /* Innertable Table data settings */
        .innertable tr > td {
            vertical-align: top;
        }

        /* Div Article Holder Settings */
        .divBorder {
            margin-bottom: 10px;
            border: solid; 
            border-color: #c4ef8b; 
            border-width: 4px 0px 0px 0px;
        }

        /* Article Image settings */
        .articleImg {
            height:50px; 
            width: 50px;
        }

        /* DivBorder Mouse Hover */
        .divBorder:hover {
            cursor: pointer;
            background-color: #f3ffe5;
        }
    </style>
</head>

<body>
    <table class="outterTable" id="newsContent"></table>
</body>

<script>
    var request = new XMLHttpRequest();
    request.open ('GET', 'https://api.iextrading.com/1.0/stock/spy/news')

    //on request load
    request.onload = function() {
        //VARIABLES
        var newsContainer = document.getElementById("newsContent");

        var JSONData = JSON.parse(request.responseText);
        var articleAmount = JSONData.length;
        var rowAmount = articleAmount / 3;
        var rowAmountRoundDown= Math.trunc(rowAmount); 
        var rowAmountRoundUp = (Math.trunc(rowAmount) + 1);
        var remainder = (rowAmount - Math.floor(rowAmount)).toFixed(2); //.00, .67, or .33;

        //=== TABLE CREATOR =============================================
        //Create an "<tbody>" element
        let tbodyHTML = document.createElement('tbody');

        //"Assembler" inside is "createTable()"
        tbodyHTML.innerHTML = createTable();

        //FUNCTION Create Table
        function createTable() {
            var tData = '';
            var index = 0; 

            //========= First Table Part Row Loop ===========================================================
            for (var i = 1; i <= rowAmountRoundDown; i++) {         
                //Row Start
                tData = tData + `
                    <tr>
                `;

                //Content: <td> <div> <table> <tr> <td>
                for (var c = 1 + index; c < 4 + index; c++) {
                    tData = tData + `
                        <td style="width: 33.33%; padding: 0px 25px">
                            <div class="divBorder">
                                <table class="innerTable">
                                    <tbody>
                                        <tr>
                                            <td>
                                                <img class="articleImg" src="images/seeking-alpha-badge.png" id="image${c}">

                                            </td>
                                            <td style="padding-left: 5px">
                                                <h3 id="headline${c}"></h3>
                                            </td>
                                        </tr>
                                    </tbody>
                                </table>        
                            </div>
                        </td>
                    `;
                }

                //Row End
                tData = tData + `
                    </tr>
                `;

                index = index + 3;
            }

            //========= Second table part =====================================================================
            //If remainder is .67 create 2 <td>
            if (remainder == 0.67) {
                //Row Start
                tData = tData + `
                <tr>
            `;

            //Content: <td> <div> <table> <tr> <td> 
            for (var c2 = (1 + index); c2 < (3 + index); c2++){
                tData = tData + `
                    <td style="width: 33.33%; padding: 0px 25px">
                        <div class="divBorder">
                            <table class="innerTable">
                                <tbody>
                                    <tr>
                                        <td>
                                            <img class="articleImg" src="images/seeking-alpha-badge.png" id="image${c2}">

                                        </td>
                                        <td style="padding-left: 5px">
                                            <h3 id="headline${c2}"></h3>
                                        </td>
                                    </tr>
                                </tbody>
                            </table>        
                        </div>
                    </td>
                `;
            }               

            //row End
            tData = tData + `
                </tr>
            `;

            //If remainder is .33 create 1 <Td>
            } else if (remainder == 0.33) {
                //Row Start
                tData = tData + `
                    <tr>
                `;

            //Content: <td> <div> <table> <tr> <td> 
            for (var c = (1 + index); c < (2 + index); c++){
                tData = tData + `
                    <td style="width: 33.33%; padding: 0px 25px">
                        <div class="divBorder">
                            <table class="innerTable">
                                <tbody>
                                    <tr>
                                        <td>
                                            <img class="articleImg" src="images/seeking-alpha-badge.png" id="image${c}">

                                        </td>
                                        <td style="padding-left: 5px">
                                            <h3 id="headline${c}"></h3>
                                        </td>
                                    </tr>
                                </tbody>
                            </table>        
                        </div>
                    </td>
                `;

            }               

            //row End
            tData = tData + `
                </tr>
            `;

            //Anything else dont do anything
            } else {
                tData = tData;
            }

            return tData;
        }

        //Inject into the HTML
        newsContainer.appendChild(tbodyHTML);
        //===============================================================
        var red = (JSONData.length + 1)
        console.log(red);

        //Output data to html
        for (var l = 1; l < red; l++){
            console.log("l: " + l);
            spyOutputToHTML(JSONData, l);
        }

    };

    function spyOutputToHTML(data, i) {
        //get current variables in this HTML page x3
        var offset = i - 1;
        var headline = document.getElementById(`headline${i}`);

        //Get Content From the JSON file ex: ".latestPrice"
        var JSONHeadline = data[offset].headline;

        //Inject data into HTML
        headline.innerHTML = JSONHeadline;
    }

    request.send()
</script>

【问题讨论】:

  • 不要将 HTML 字符串与 DOM 元素创建混合和匹配。只需使用 DOM,尤其是 Table API
  • 我已将此代码实施到我的网站中。你可以在这里看到它的实际效果:yieldsync.com 我仍然需要修复它并尝试整合下面精彩用户评论的内容

标签: javascript json html-table elixir-iex


【解决方案1】:

首先,干得好! 对于 javascript 新手来说,这是令人印象深刻的工作

几乎没有什么可以改进的,但我看不出你做错了什么。也许,只有remainder 的逻辑太混乱了。我敢打赌应该有更简单的方法

可读性

如果您将视图(模板)逻辑、请求逻辑和数据“按摩”逻辑分开,您的代码无疑会更容易阅读和理解

视图逻辑

通常,“手动”构建 HTML 结构(createElementappendChild)需要更多的努力,并且可以说,与使用模板函数渲染字符串(有点像你所做的)和注入相比,更令人困惑你需要的结果。混合这些方法比“手动”做所有事情更容易出错。所以,我建议你有一个视图/模板函数,它可以获取数据并返回一个字符串

function renderTable(data) {
    var result = '<div>';
    // build the result string...
    result += '</div>';
    return result;
}

// and then...
targetEl.innerHTML = renderTable(data);

您可能还想利用micro-templating。对于更大的应用程序,一种或另一种模板将是必不可少的。让自己熟悉模板引擎。对于您的项目,使用 javascript 构建字符串很好。不过,您可以考虑更多 advanced 技术

数据“按摩”逻辑

嗯,这归结为让您的模板函数对其上下文不“聪明”(基本的关注点分离),并且只使用数据。不“烹饪”它,只吃它:)

所以,不要这样做

function renderTable(data) {
    var result = '<div>';
    var something = data.abc * data.xyz;
    // do something with something here
    result += '</div>';
    return result;
}

targetEl.innerHTML = renderTable(data);

...你这样做

function adaptResponsePayloadData(data) {
    var result = { ...data };
    result.something = result.abc * result.xyz;
    return result;
}

function renderTable(data) {
    // ...
}

targetEl.innerHTML = renderTable(adaptResponsePayloadData(data));

这是所谓的适配器设计模式的一个例子。这是使用它的正确案例。还有很多其他design patterns,我强烈建议您花时间熟悉它们

请求逻辑

这里的另一个关注点分离。您可以将请求逻辑放在单独的函数中,类似于我们如何将“按摩”从上面的视图中分离出来

const API_ENDPOINT_URL = 'https://api.iextrading.com/1.0/stock/spy/news';

function fetchData(callback) {
    var request = new XMLHttpRequest();
    request.open('GET', API_ENDPOINT_URL);
    request.onLoad(() => {
        var data = JSON.parse(request.responseText);
        callback(data);
    });
    request.send();
}

// ... and then
fetchData(data => {
    // ...
    targetEl.innerHTML = renderTable(adaptResponsePayloadData(data));
});

执行顺序注意事项

有一个经验法则可以在代码运行时明确说明。这完全是一个挑剔,但可以在代码级别将什么与什么分开

function goOn() { // there are many conventional names for this, like `main`
    fetchData(data => {
        document.body.innerHTML = renderTable(adaptResponsePayloadData(data));
    });
}

window.onload = goOn;

关于 HTML 和 CSS 的说明

  1. 你真的不需要&lt;tbody&gt;。除非您想使用 CSS 突出显示某些内容,否则不需要它

  2. 避免使用内联样式,例如&lt;td style="width: 33.33%; padding: 0px 25px"&gt;。你可以用 CSS 来表达

  3. 您不需要 divBorder 类。为父级td添加内边距,为子级table添加边框

其他小笔记

通常,第一个大写字母的名称是对象构造函数或类。简单地说,将常规 var 名称设为小写形式,例如 jsonHeadline

JSON 是我们所知道的符号术语。当我们解析该符号的字符串时,它就变成了datacontextData,你明白了……然后,数据里面的内容就变成了headline

尽最大努力命名变量,这样您就不必编写 cmets 来理解您的意思。寻找其他好的提示here

确保您的生产代码没有console.log 语句

let 关键字比var 更安全。你永远不会用它污染全局范围


请注意Code Review on StackExchange,您可以在其中学习如何编写出色代码的许多其他方面

你做得很好。祝您旅途愉快! :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-13
    相关资源
    最近更新 更多