2016-10-16 11 views
3

私が直面している課題は、プレーンな古いJavascriptで単一ページのアプリケーションを構築することです。ライブラリやフレームワークは許可されていません。 ReactとAngularで動的なDOM要素を作成するのはかなり簡単ですが、私が思いついたバニラのJSソリューションはぎこちないようです。動的にレンダリングされたDOM要素を構築するために特に簡潔で効率的な方法があるのだろうかと思います。プレーンなJSでDOM要素を動的にレンダリングするにはどうすればよいですか?

以下の関数は、GETリクエストから受け取った配列を受け取り、各アイテムのdivをレンダリングして値を渡します(結果をReactとrenderの子要素にマップするのと同じように)。

function loadResults(array) { 
    array.forEach(videoObject => { 
    let videoData = videoObject.snippet; 
    let video = { 
     title : videoData.title, 
     img : videoData.thumbnails.default.url, 
     description : videoData.description 
    }; 
    let div = document.createElement("DIV"); 
    let img = document.createElement("IMG"); 
    img.src = video.img; 
    let h4 = document.createElement("h4"); 
    let title = document.createTextNode(video.title); 
    h4.appendChild(title); 
    let p = document.createElement("p"); 
    let desc = document.createTextNode(video.description); 
    p.appendChild(desc); 

    div.appendChild(img); 
    div.appendChild(h4); 
    div.appendChild(p); 
    document.getElementById('results') 
     .appendChild(div); 
    }); 
} 

これは不必要に不器用なように感じますが、私はこれを行う簡単な方法がまだ見つかりませんでした。

ありがとうございます!

+0

を動的な要素を構築する関数...そのようにすれば、その要素を構築するために関連する情報を渡す関数への関数といくつかの呼び出ししかないでしょう...それで、ソースコードが厄介なように見えるのです... – NewToJS

+1

パフォーマンスヒットに気にしなければ 'innerHTML'を実行してください。 – Dai

+1

あなたが持っているものは、ReactやAngularではなく、普通のJSで要素を作成するための適切な方法です。 – adeneo

答えて

9

注:私がここで言うすべては、概念レベルの証拠に過ぎません。エラーや例外的なケースは処理されず、本番環境では もテストされませんでした。あなたの自由裁量で使用してください。

良い方法は、要素を作成する関数を作成することです。このような何か:

const crEl = (tagName, attrs = {}, text) => { 
    const el = document.createElement(tagName); 
    Object.assign(el, attres); 
    if (text) { el.appendChild(document.createTextNode(text)); } 

    return el; 
}; 

は、その後、あなたがそうのようにそれを使用することができます:

results 
    .map(item => crEl(div, whateverAttributes, item.text)) 
    .forEach(el => someParentElement.appendChild(el)); 

私が見てきた概念のもう一つのクールな証拠は、ES6 Proxies as a sort of templating engineの使用です。

const t = new Proxy({}, { 
 
    get(target, property, receiver) { 
 
    return (children, attrs) => { 
 
     const el = document.createElement(property); 
 
     for (let attr in attrs) { 
 
     el.setAttribute(attr, attrs[attr]); 
 
     } 
 
     for (let child of(Array.isArray(children) ? children : [children])) { 
 
     el.appendChild(typeof child === "string" ? document.createTextNode(child) : child); 
 
     } 
 
     return el; 
 
    } 
 
    } 
 
}) 
 

 
const el = t.div([ 
 
    t.span(
 
    ["Hello ", t.b("world!")], { 
 
     style: "background: red;" 
 
    } 
 
) 
 
]) 
 

 
document.body.appendChild(el);

プロキシ(空である)対象オブジェクトのgetを捕捉し、呼び出されたメソッドの名前を持つ要素をレンダリングします。これは、const el =として表示される本当にクールな構文につながります。

+1

'style'属性は実世界でカバーする必要がある共通の特殊なケースです - ' el.style.color = "red" '; 'el.style = {color:" red "}'はしません。 – joews

2

テンプレートエンジンを使用していない場合は、できるだけ要素をどのように組み立てるかを十分にコントロールしたいと考えています。だから健全なアプローチは、一般的なタスクを抽象化し、コールを連鎖させて余分な変数を避けることです。だから私は、この(非常に派手ではない)のようなものでいいと思う:

function CE(el, target){ 
    let ne = document.createElement(el); 
    if(target) 
     target.appendChild(ne); 
    return ne; 
} 

    function CT(content, target){ 
    let ne = document.createTextNode(content); 
    target.appendChild(ne); 
    return ne; 
} 


function loadResults(array) { 
    var results = document.getElementById('results'); 
    array.forEach(videoObject => { 
    let videoData = videoObject.snippet; 
    let video = { 
     title : videoData.title, 
     img : videoData.thumbnails.default.url, 
     description : videoData.description 
    }; 
    let div = CE('div'); 
    let img = CE("IMG", div); 
    img.src = video.img; 
    CT(video.title, CE("H4", div)); 
    CT(video.description, CE("p", div);); 

    results.appendChild(div); 
    }); 
} 

あなたが得る何をどのようにリンクされているものを、あなたはまだあなたの要素が組み立てられている方法についての細かな制御を持っているということです。しかし、あなたのコードは従うのが簡単です。

3

あなたはES6を使用することができた場合は、テンプレートの文字列は別の考えである - このcode review質問について>

var vids = [ 
 
    { 
 
    snippet: { 
 
     description: 'hello', 
 
     title: 'test', 
 
     img: '#', 
 
     thumbnails: { default: {url: 'http://placehold.it/64x64'} } 
 
    } 
 
    } 
 
]; 
 

 
function loadResults(array) { 
 
    array.forEach(videoObject => {  
 
    let videoData = videoObject.snippet; 
 
    let video = { 
 
     title : videoData.title, 
 
     img : videoData.thumbnails.default.url, 
 
     description : videoData.description 
 
    }; 
 
    document.getElementById('results').innerHTML = ` 
 
<div> 
 
    <img src="${video.img}"/> 
 
    <h4>${video.title}</h4> 
 
    <p>${video.description}</p> 
 
</div> 
 
`; 
 
    }); 
 
} 
 

 
loadResults(vids);
<div id="results"></div>

0

2つの観測:

追加
  1. によって

    リファクタリングヘルパ関数を作成するオプションのテキストコンテンツを持つ要素、および

  2. それと同じ名前でコピー3つのうち2つのプロパティ、

は読めるけど、バニラタイプJavascriptを生成するのでvideoオブジェクトの抽象化を取り除く:あなたが作成することができ

function loadResults(array) { 
    function create (type,text) { 
     let element = document.createElement(type); 
     if(text) 
      element.appendChild(document.createTextNode(text)); 
     return element; 
    } 
    array.forEach(videoObject => { 
     let vid = videoObject.snippet; 
     let div = create("DIV"); 
     let img = create("IMG"); 
     img.src = vid.thumbnails.default.url; 
     let h4 = create("H4", vid.title); 
     let p = create("P", vid.description); 

     div.appendChild(img); 
     div.appendChild(h4); 
     div.appendChild(p); 
     document.getElementById('results').appendChild(div); 
    }); 
} 
関連する問題