如何简化此代码?有更好的方法吗?

时间:2019-02-07 01:15:03

标签: javascript json html-table iex

经过数小时的压力,我才使这段代码正常工作。我是Java语言的新手,所以不确定是否以最有效的方式进行了此操作。我正在使用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>

1 个答案:

答案 0 :(得分: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. 您真的不需要<tbody>。除非您要使用CSS突出显示内容,否则不需要它。

  2. 避免使用内联样式,例如<td style="width: 33.33%; padding: 0px 25px">。您可以使用CSS来表达这一点

  3. 您不需要divBorder类。在父td上添加填充,在子table上添加边框

其他小笔记

通常,首字母大写的名称是对象构造函数或类。只需将常规变量名称设置为lowerCamelCase,例如jsonHeadline

JSON是我们知道的表示法术语。当我们解析该表示法的字符串时,它就变成datacontextData,您就明白了...然后,数据中的内容就变成了headline

尽最大可能为变量命名,这样您就不必编写注释来理解您的意思了。找到其他好的秘诀here

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

let关键字比var安全。您永远不会污染全球范围


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

您的确很棒。祝您旅途愉快! :)

相关问题