在如今無論是單向還是雙向綁定的各類V
框架中, 我們大多數時候其實不需要用上以前字符串模板拼接的html
, 甚至是對于html
本身的編寫, 也大部分都是在.vue
或是.jsx
中了, 即便如此, 在維護一些比較久遠的代碼時, 還是會遇到一些問題, 而今天便是討論下關于傳參的方式
首先html
結構為
<ul id="ul"></ul>
對應的有如下需要渲染到ul
中的一個數據
let arr = [
{ num: 1, str: '行1', obj: { a: 1, b: 2 }, arr: [1, 2] },
{ num: 2, str: '行2', obj: { a: 2, b: 3 }, arr: [3, 4] },
]
那么如果需要將這個數據渲染出來并且傳入這個數據本身, 對于vue
之類的框架而言, 只需要v-for
和@click
直接綁定就可以, 不過對于原生而言, 這種方式其實并不理智, 也不對
原生如果需要直接實現@click(params)
的話, 對應的自然也就是綁定在onclick(item)
中, 那么實現的方式會是這樣
arr.forEach(item => {
html += `<li onclick='handle(event, ${JSON.stringify(item)})' >${item.str}</li>`;
})
那么這種方式會有什么問題呢?他會暴露整個對象在html
中, 也就是下圖
所以按我的經驗來說的話, 我會更加建議將參數傳入到data-xxx
中, 不過當然也是半斤八兩, 畢竟前端代碼就是給別人看的, 不懂的沒必要偽裝, 懂的也沒辦法偽裝, 我這里的經驗更多的是應對于后續維護調試, 可以排除大量不需要的屬性, 定位問題更加容易, 就像是在vue
中我更多的是直接用解構賦值來獲取參數, 比如
<a @click="handle(item)" v-for="(item, index) in list" :key="item.id"></a>
handle({ id, name, department }) { }
那么如果想要傳入整個對象, 但是又不愿意將其暴露在html
中的話, 那該怎么綁定呢, 也是有方法的, 那便是利用閉包, 也就是以下的綁定方式
arr.forEach((item) => {
let id = `li${item.num}`;
let dom = document.createElement('li');
dom.innerHTML = item.str + `一些比較復雜的html,比如<div><div><a href='javascript:;'>點擊鏈接</a></div></div>`;
dom.addEventListener('click', function(event) { console.log(event, item) });
ul.append(dom);
})
可以從代碼中看到, 這個li
節點將是直接生成而非字符串拼接, 這樣的好處在于可以直接獲取這個li
節點, 從而利用js
的閉包將當前循環的item
對象直接傳入到綁定方法中, 但是閉包有好處自然也有壞處, 這種方式如果綁定的多, 對于內存的消耗自然也不小, 所以使用這種方式的話, 需要稍微考慮性能的問題, 不過當然, 一般情況下應該采用其他方式來處理這種問題, 比如按視圖加載, 分頁處理, 都是用來解決這類大量點擊綁定的好方法。