2017-10-15 55 views
0

我建立了一个网页,检测您当地的天气预报。但是,为了使它具有独特性,我试图让网页在界面上改变颜色。它会根据天气api中的哪个天气图标更改颜色。 (即weath.weather [0] [“icon”])。我试图让它运行得尽可能快,同时让它更容易理解。所以我正在寻找一种替代方法。款式/颜色多种元素,通过使用的setAttribute(的)(JavaScript)的

我决定来存储颜色变化功能在一个变量,因此它可以被多次重复使用,所以我可以缩短switch语句。它包含一个可以重用的CSS字符串变量。字符串为函数的setAttribute造型属性:

var coloring = function(id, Text, Background) { 
    var colorChange = "color: " + Text + "; background: " + Background + ";"; 
    document.getElementById(id).setAttribute("style", colorChange); 
}; 

这将被用于通过参照它们的id来改变DOM的各种元件/部分的颜色。下面是DOM:

<body id="background"> 
 
    <div id="header"> 
 
<h1>Local Weather Detector</h1> 
 
    </div> 
 
    <div id="location"> 
 
    <h5 id="locIntro">Today's weather from Location...</h5> 
 
    </div> 
 
    <div id="box"> 
 
    <div id="temperature"> 
 
    <p><strong>Today, </strong>The temperature in your area is... 
 
    <button id="tempSwap"> 
 
     </button></p> 
 
    </div> 
 
    
 
    <div id="weather"> 
 
    <p>- and the general forecast is...</p> 
 
    </div> 
 
    </div> 
 
    <div id="copywrite"><h6> &#9400; Thomas Jackson</h6> 
 
     <h6>(Project for Free Code Camp, Full Stack course)</h6></div> 
 
</body>

我会得到来自API的图标数据,则switch语句将决定需要根据哪个图标就改变什么颜色。与使用着色()函数中的每一个开关箱会改变DOM的颜色,以自己的一套颜色:

$.getJSON(api, function(weath) { 

    switch (weath.weather[0]["icon"]) { 

     case "01d": //clear 
     coloring("background", "#f1c40f", "#3498db"); 
     coloring("box", "#2980b9", "#ecf0f1"); 
     coloring("temp", "#c0392b", ""); 
     break; 
     case "01d": 
     case "03d": 
     case "04d": 
     case "50d": //cloud 
     coloring("background", "#3498db", "#ecf0f1"); 
     coloring("header", "#f1c40f", ""); 
     coloring("box", "", "#2980b9"); 
     coloring("temp", "", "#3498db"); 
     break; 
     case "02d": //cloudClear 
     coloring("background", "c0392b", "#2980b9"); 
     coloring("header", "#f1c40f", ""); 
     coloring("box", "", "#ecf0f1"); 
     coloring("temp", "", "#2980b9"); 
     break; 
     case "11d": //thunder 
     coloring("background", "#c0392b", "#2980b9"); 
     coloring("header", "#f1c40f", ""); 
     coloring("box", "", "#f1c40f"); 
     coloring("temp", "", "#c0392b"); 
     break; 
     case "13d": //snow 
     coloring("background", "#ecf0f1", "#2980b9"); 
     coloring("header", "#34495e", ""); 
     coloring("box", "", "#a5f2f3"); 
     coloring("temp", "", "#34495e"); 
     break; 
     case "03n": 
     case "04n": 
     case "50n": //cloudNight 
     coloring("background", "#ecf0f1", "#7f8c8d"); 
     coloring("header", "#e74c3c", ""); 
     coloring("box", "#f1c40f", "#34495e"); 
     coloring("temp", "", "#2c3e50"); 
     break; 
     case "09n": 
     case "10n": //rainNight 
     coloring("background", "#3498db", "#2c3e50"); 
     coloring("header", "#f1c40f", ""); 
     coloring("box", "#2980b9", "#95a5a6"); 
     coloring("temp", "#3498db", "#2980b9"); 
     break; 
     case "11n": //thunderNight 
     coloring("background", "#f1c40f", "#2c3e50"); 
     coloring("header", "#e74c3c", ""); 
     coloring("box", "#c0392b", "#f1c40f"); 
     coloring("temp", "", "#c0392b"); 
     break; 
     case "13n": //snowNight 
     coloring("background", "#f1c40f", "#2c3e50"); 
     coloring("header", "#a5f2f3", ""); 
     coloring("box", "#34495e", "#a5f2f3"); 
     coloring("temp", "#2c3e50", "#f1c40f"); 
     break;} 

} 

如果我要对这个错误的方式,将是很好的了解。我的主要目标是让其他开发人员更高效,更清晰。

+0

由于代码已经是功能性的,我认为这个问题更适合在代码审查stackexchange:https://codereview.stackexchange.com/ 。在那里,人们可能会给你更好的反馈。 –

+0

谢谢。有没有办法将这个转移到StackExchange代码审查与复制和粘贴? –

+0

我不认为它有可能在那里移植它。 –

回答

0

你要对这个办法其实不是太远了,从我称之为“正确”的方式(通常有不止一个) - 有空间的一对夫妇微优化和清晰度增强器。

首先,如果你想增加其他的维护者可读性,我建议你存储命名常量的图标代码。一个case: "01d"没有告诉我的图标是什么什么,但是这并不:

var ICON_STORMY = "01d"; 
switch (weath.weather[0].icon) { 
    case ICON_STORMY: 
     ... 
     break; 
    ... 
} 

其次,你的着色功能是相当严重,所以我就拧紧了一点太 - 得不多,但也许只是这样,它可以被调用一次,而不是每个id一次。

你可以,例如,写像这样:

function colorAll(elems) { 
    elems.forEach(function (elem) { 
     var colorChange = "color: " + elem.text + "; background: " + elem.background + ";"; 
     document.getElementById(elem.id).setAttribute("style", colorChange); 
    }); 
} 

...然后使用像这样的功能:

colorAll([{ id: 'background', text: 'blah blah', background: '#666666' }, { ... }]); 

...的想法是,它只需要被调用一次,如果你通过完成整个开关案例所需的所有信息。

+0

感谢您的反馈意见。事实上,你说的“正确”方式离我们不远,这告诉我我正在改进。我明白你来自使用变量的地方。但我不是更好地使用对象列表而不是个别变量吗?我有一个以前的对象列表形式的图标选择列表。我摆脱了它,因为我认为它会跑得更快,我只是在每个开关盒旁边写上引号。正如你所看到的,我已经做到了。无论如何感谢您的反馈。 –

+0

@TommyJackson是的!你打赌,这绝对是那种“比一种”更多的方式。在一个switch语句和一个object map之间,无论你选择哪一个小数值,你的性能收益在差异上都可以忽略不计。如果您希望特别聪明(以一些可读性为代价),您甚至可以通过图标代码(如{'01d':{text:'...'等})来键入对象。 – wosevision

+0

但是,只要在每个开关盒旁边添加引号,我会不会更好?那会使用更少的代码,并解释每个代码。 –

0

在功能

switch声明思考是很有用的,但它不适合与功能代码休息你write.It有副作用,变异状态,副作用的机会,主要是不能与其它功能

组成应该有几乎总是一个switch语句中默认情况下。我假设。如果在 weath.weather[0]["icon"]的情况下没有发现相关值,则说明案件未注册。让我们来看看我们正在处理的开关盒

$.getJSON(api, function(weath) { 

switch (weath.weather[0]["icon"]) { 

    case "01d": //clear 
    coloring("background", "#f1c40f", "#3498db"); 
    coloring("box", "#2980b9", "#ecf0f1"); 
    coloring("temp", "#c0392b", ""); 
    break; 
    case "01d": 
    case "03d": 
    case "04d": 
    case "50d": //cloud 
    coloring("background", "#3498db", "#ecf0f1"); 
    coloring("header", "#f1c40f", ""); 
    coloring("box", "", "#2980b9"); 
    coloring("temp", "", "#3498db"); 
    break; 
    default: 
    console.log(`case is not registered`); 
    break; 
    } 

} 

如果我们转换成三元代码看起来像这样。我使用ES6箭头功能更好的可读性

$.getJSON(api,(weath) => { 

    const icon = weath.weather[0].icon; 

    // try to convert switch to if/else or ternary 

    icon === '01d' ? coloring() : //coloring methods of 01d 
    icon === '02d' ? coloring() //coloring methods of 02d 
        : console.log('no case matched'); 

}); 

此重复的代码可以用功能进行优化像以下

const switchcase = (cases, defaultCase, key) => { 

     if (key in cases) { 
     return cases[key] 
     } else { 
     return defaultCase 
     } 
} 

应用钻营技术上述方法并使用三元取代传统if else

const switchcase = cases => defaultCase => key => 
    key in cases ? cases[key] : defaultCase 

现在的代码可以优化如下

$.getJSON(api, switchcase({ 
    '01d' : coloring1(), 
    '02d' : coloring2() 
    })(console.log('no case matched'))(weath.weather[0].icon) 
); 

switchcase这个早期版本有一个问题,因为在传递给switchcase函数之前,整个对象字面值会被求值。这意味着coloring1()coloring2()都被评估。这可能是非常危险的。

如果对象字面值中的值是函数,那么只有存在匹配的大小写时才可以执行它们。

代码将变为

$.getJSON(api, switchcase({ 
    '01d':() => { coloring('x');coloring('...');}, 
    '02d':() => { coloring('y');coloring('...');} 
    })(() => console.log('no cases matched'))(weath.weather[0].icon) 
); 

代码优化

$.getJSON(api, switchcase({ 
    01d:() => coloringClear(), 
    03d:() => coloringCloud(), 
    04d:() => coloringCloud(), 
    50d:() => coloringCloud(), 
    02d:() => coloringCloudClear(), 
    11d:() => coloringThunder(), 
    13d:() => coloringSnow(), 
    03n:() => coloringCloudNight(), 
    04n:() => coloringCloudNight(), 
    50n:() => coloringCloudNight(), 
    09n:() => coloringRainNight(), 
    10n:() => coloringRainNight(), 
    11n:() => coloringThunderNight(), 
    13n:() => coloringSnowNight() 
    })('Unknown')(weath.weather[0]["icon"]) 
); 

保存在单独的变量中的对象为更好的可维护性。将所有着色方法移动到上面指定的一种方法中。它们写成单独的功能

希望将优化性能与上面的代码