javascript - 我如何简化这段代码?有更好的方法吗?

标签 javascript json html-table elixir-iex

经过几个小时的压力,我刚刚让这段代码开始工作。我是 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>

最佳答案

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

确实没有什么可以改进的,但我不认为你做错了什么。也许,只有 remainder 的逻辑太困惑了。我打赌应该有一个更简单的方法

可读性

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

View 逻辑

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

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我强烈建议您花时间熟悉它们

请求逻辑

这里还有一个值得关注的分离问题。您可以将请求逻辑放在单独的函数中,类似于我们从上面的 View 中分离“按摩”的方式

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类(class)。向父级添加填充 td和 child 的边框table

其他小注释

按照惯例,第一个大写字母的名称是对象构造函数或类。简单地说,将常规变量名称设为小驼峰命名,例如 jsonHeadline

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

尽力命名变量,这样您就不必编写注释来理解您的含义。查找其他好提示here

确保您的生产代码没有 console.log声明

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

<小时/>

请注意有Code Review on StackExchange在这里您可以学习如何编写优秀代码的许多其他方面

你做得真棒。祝您旅途顺利! :)

关于javascript - 我如何简化这段代码?有更好的方法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54564972/

相关文章:

javascript - 如何从 Blob url 检索 MediaStream?

javascript - 无法触发事件 $.mobile.changePage

java - @JsonSerialize 与泛型

javascript - 表格悬停边框颜色删除列线

JQuery 删除动态表上的行

html - 对齐表格中的元素

javascript - ios应用程序后退按钮不保存cookie

javascript - 如何使用 angular4 上的输入调整 iframe 宽度?

javascript - 选择 Maya 到 JSON 库

c# - 如何使用 Json.NET 填充 IList 集合