0

次のコードは問題なく動作しますが、改善したいと思います。

function prodNameTrim(selector){
        var el = document.getElementsByClassName(selector);
        var len = el.length;
        for(i = 0; i<len; i++){
            aObj = el[i].getElementsByTagName('a');
            txtNode = aObj[0].childNodes[0].nodeValue;
            if(txtNode.length > 26){
                txtNode = txtNode.substring(0, 27) + ' ...';
            }
            aObj[0].childNodes[0].nodeValue = txtNode;
        }
    }

私が気に入らないのは、次のように条件の前に最初に txtNode を確立することです。

txtNode = aObj[0].childNodes[0].nodeValue;

条件付きで変数を処理して文字列を省略記号で切り捨てた後、次の手順を実行して DOM 内のテキストを置き換えます。

aObj[0].childNodes[0].nodeValue = txtNode;

これを行うためのより良い方法があると信じなければなりませんが、それが何であるかはわかりません.DRYルールを破っているように感じます.

4

4 に答える 4

2

私はこれを提案します:

function prodNameTrim(selector){
    var el = document.getElementsByClassName(selector),
        len = el.length, node;
    for(var i = 0; i < len; i++) {
        node = el[i].getElementsByTagName('a')[0].firstChild;
        if(node.nodeValue.length > 26){
            node.nodeValue = node.nodeValue.substring(0, 27) + ' ...';
        }
    }
}

変更点:

  1. すべてのローカル変数を宣言します (したがって、暗黙的なグローバルはありません - iaObjまたはを宣言していませんでしたtxtNode)
  2. aObj中間体は不要なので飛ばします
  3. textNode 中間体は必要ないので避ける
  4. nodeValue に直接割り当てる
  5. nodeValue への代入はifステートメント内でのみ行います。それが変更される唯一の場所だからです。
  6. .firstChildの代わりに使用.childNodes[0]

これが機能するかどうかは疑問ですが (おそらく IE9 以上が必要で、HTML を確認してブラウザー テストを実行したいと考えています)、一般的な考え方はquerySelectorAll()、2 つの検索を使用して、より複雑な CSS セレクターに結合することです。

function prodNameTrim(rootClass) {
    var items = document.querySelectorAll("." + rootClass + " a:first-of-type"), node;
    for (var i = 0; i < items.length; i++) {
        node = items[i].firstChild;
        if (node.nodeValue.length > 26) {
            node.nodeValue = node.nodeValue.substring(0, 27) + ' ...';
        }
    }
}

この 2 番目の実装では、引数 toprodNameTrim()がクラス名であると想定していることに注意してください (OP のバージョンと同様)。


または、各セレクターの親にリンク タグが 1 つしかない場合は、これを使用するだけで、最新のすべてのブラウザーで動作するはずです。

function prodNameTrim(rootClass) {
    var items = document.querySelectorAll("." + rootClass + " a"), node;
    for (var i = 0; i < items.length; i++) {
        node = items[i].firstChild;
        if (node.nodeValue.length > 26) {
            node.nodeValue = node.nodeValue.substring(0, 27) + ' ...';
        }
    }
}
于 2013-10-15T21:00:44.420 に答える
2

aObj[0].childNodes[0]どこでもその部分を繰り返さないようにしたい場合は、txtNode変数を使用して、値ではなくノード自体を参照できます。

function prodNameTrim(selector){
    var el = document.getElementsByClassName(selector);
    var len = el.length;
    var txtNode;  // declare txtNode with var
    for(var i = 0; i<len; i++){
        txtNode = el[i].getElementsByTagName('a')[0].childNodes[0];
        if(txtNode.nodeValue.length > 26){
            txtNode.nodeValue = txtNode.nodeValue.substring(0, 27) + ' ...';
        }
    }
}

どこでも繰り返すことになりますが、毎回txtNode.nodeValue含める必要があるよりはましです。aObj[0].childNodes[0]また、部分文字列バージョンをノードに書き戻すステートメントの後にあった行ifは不要です。これは、その更新がif.

また、すべての変数を で宣言する必要があることにも注意してください。そうしないと、変数varがグローバルになります。aObj(そして、上で示した方法では、実際には変数はまったく必要ありません。)

于 2013-10-15T20:52:52.773 に答える
1

条件付きの切り捨てを 1 行で実行したい場合は、次のようにすることができます。

function prodNameTrim(selector){
    var el = document.getElementsByClassName(selector),
        len = el.length, node;
    for(var i = 0; i < len; i++) {
        node = el[i].getElementsByTagName('a')[0].firstChild;
        node.nodeValue.substring(0, 27) + (node.nodeValue.length > 26 ? ' ...', '')
    }
}
于 2013-10-15T21:10:18.847 に答える
0

不要なグローバル変数を導入しているという事実を除いて、あなたは正しい方法でやっています。最初の割り当ては次のとおりです。

var txtNode = aObj[0].childNodes[0].nodeValue;

varステートメントを使用してください!for関数の先頭で、ループの前に変数を宣言することもできます。innnnnn が指摘したように、との意図しないグローバルも作成していますaObjforしたがって、ループの直前にこれを挿入することで、3 つの問題をすべて解決できます。

var i, aObj, txtNode;
于 2013-10-15T20:52:42.240 に答える