ホームページ  >  記事  >  ウェブフロントエンド  >  HTML DOM を操作するためのネイティブ API を破壊するノード操作用の API ノード_JavaScript スキル

HTML DOM を操作するためのネイティブ API を破壊するノード操作用の API ノード_JavaScript スキル

WBOY
WBOYオリジナル
2016-05-16 18:13:58855ブラウズ

第一次看到敏捷开发的定义,我就被敏捷开发迷住了。通俗来说,敏捷开发可以让我们用过的代码可以再次重用,因为是再次重用,所以相对安全,再次调试也没有第一次那么费心,省时省力。不断重用代码的过程中把存在的bug不断的修复,也因为不断的去重用, 这个模板变得起越来越独立,适用的情况越来越广范,最后在安全方面达到铜墙铁壁,在开发方面达到随心所欲,在维护方面达到从容面对。

敏捷开发的确是利害,但如何练就这种深奥的武功呢?就我自身的情况靠人传授武功是不可能了,因为公司就我一个做开发的,苦思幂想之后,决定从开源的优秀框架入手,把它一行一行代码看懂,然后再为我所用。因为是一个人开发,前台和后台都得包办,哪从那一面做起呢? 之前有过一二个月的开发经验,觉得前台的JS很费时,而且老觉得在做重复的事情,比如发ajax请求,接收结果之后操作节点(有时候遇到不兼容的情况,如select和table在IE下不支持使用innerHTML,style在IE不会自动转化为字符串,要用cssText代替,一旦这些情况遇上,真得是无比打击程序员的积极性,因为你要为此花时间去找替代方案,去调试),还有节点轮换,弹出层,表单验证等一系列烦琐工作。所以我就坚决从前台的JS做起。为了练就怎么把JS的重用性提高,我选择向Jquery取经。花了几个月看了一大半,略有所得。我其中之一的JS模块“无限深度操作节点”(文采不好,名字不妥别见怪)出来了。有了它,我在操作节点方面变得容易,代码变得精简,而且不用写额外的代码去兼容浏览器,谈笑中,功能就完成了。

首先我谈谈是什么让操作节点给我们带来烦恼:
  • 编写ajax程序时,动态增删改页面元素几乎是不可避免的,使用属性innerHTML就是我们经常利用的途径,但在IE中table,thead,tfoot,tbody,tr,col,colgroup,html,title,style,frameset的innerHTML属性是只读的,也就是我们不能使用innerHTML更新这些节点。(这里没有提到select,其实select也是不会成功的,估计是IE的bug)。例子如下:(下面的$id代表document.getElementById)
    //执行代码:
    $id('jkit').innerHTML = '';
    //IE下并没有报任何错误,但select一个option节点都没有了。如果你对table使用innerHTML,IE会报unknown runtime error
     
    对于这种情况比较常用的兼容方法是外加一个外层元素,例子如下:

        
    //执行代码:
    $id('jkit').innerHTML = '';
    //这样IE也成功改变select,但这种做法有个缺点,如果你对select注册过事件,这些事件会全部丢失,你要外加代码来重新注册事件。
     
  • 在指定的节点前后新增节点,这就涉及于节点定位,节点创建以及给节点属性设置。使用innerHTML通常只用于覆盖DOM元素的所有节点,如果只想改变元素的某个子节点,或者只想在某个子节点前后增加节点,仍然使用innerHTML就适得其反,实现起来很吃力了,而且使用了innerHTML之后,对子节点注册过的事件肯定全部丢失掉。不使用innerHTML,那只好使用原生的DOM方法了,但这种代替方案也不好使,看下面例子:
    //现在我想在jkit之前多加一个option,用原生的DOM方法实现:
    var newNode = document.createElement('option'),//新建一个节点
    selector = document.getElementById('jkit3'),
    /* 也可以用selector.options,但getElementsByTagName更通用。
    那用childNodes怎么?最好也不要,对于空白节点,IE和FF的处理方式不一样,
    就这例子,在FF中,select的firstChild是空白文本节点,
    因为select和第一个option之间有换行以及空白字符,
    FF会为其创建节点,而IE会忽略 */
    options = document.getElementsByTagName('option');
    newNode.setAttribute('value','new');
    //newNode.setAttribute('text','NewNode');text不支持这样设置
    //newNode.text = 'NewNode';ie不支持这种方式
    newNode.innerHTML = 'NewNode';
    selector.insertBefore(newNode,options[1]);//在kit之前插入
     
    上記のコードを実行すると、select にはもう 1 つのオプションがあります:






    • L

    • XL










    /* 以下のコードは、新しいオブジェクトを再構築することに相当する、無制限の層のオブジェクトのオブジェクトを示しています。新しいオブジェクト バンドには、新しい作成方法があります。新しいオブジェクトの参照は table であり、table も新しいルートです。その後続オブジェクトは 2 番目のパラメータchilds によって決定されます。新しいルート参照は、後続オブジェクトを操作するためのエントリです。childs は次の 2 番目のパラメータです。数値グループの最初の要素は tr であり、dom ルート ルートの子ポイント tr が存在しない場合、新しいオブジェクトは構築されません。tr 内に tr が存在する場合、オブジェクトは再構築されません。 、 2 番目の要素は td 番目、つまり 2 つあるということですか? th は、新しいオブジェクトを構築すると同時に削除され、スペースで区切られ、検出される順序が制限されない場合には、td であってもよい。第三个元素为select ul,为什么这两个可以写在一起?因为他们位于同一层次的,相对于根节点,它们都在第三层。只要同一层次的都可以写在一起。后面的以此类推,数量不限,就是无限层次了。新对象树的层次结构和原dom树的层次结构是一一对应的。 */
    root = document.getElementById('category'),

    childs = ['tr', 'td th', 'select ul', 'li option'],

    table = $CL.newObj('maNode', [root, childs]);  
  • 新しいツリーのメンバーメソッド、次の API を読むときは、2 つの点に注意してください。まず、ルートオブジェクトと子孫オブジェクトのすべてのメソッドは、元の DOM オブジェクトに対するものです (例: del を呼び出すなど)。新しいオブジェクト。その本質は、対応する元の DOM オブジェクトを削除することです。次に、オブジェクトの追加、削除、または変更が呼び出されるたびに、対応するブランチが再構築されます

    ルートオブジェクトの固有メソッド
    function map(index1,index2,,,indexN){}
    このメソッドは、子孫ノードを検索するために使用されます。 table.map(1,1,0) は、次の行を検索します。 2 つのセルの最初のオブジェクトは、select に対応するオブジェクトです。 Map にパラメータが 1 つだけあり、そのパラメータが DOM ネイティブ オブジェクトである場合、このメソッドは対応する新しいオブジェクトを返します。
    function Index(DOMElement){}
    このメソッドは、ネイティブ DOMElement オブジェクト table.index(document.getElementById('lior')) に対応するインデックスを返し、[1, 2 ,0,0]、結果は配列形式になります
    子孫オブジェクトに固有のメソッド
    function add(index, html){}
    このメソッドは、兄弟ノードを追加するために使用されます。Index は、このメソッドを呼び出すオブジェクトの位置に対する相対的な変位です。挿入するノード、html には、W3c 標準に準拠する任意の HTML 文字列を指定できます。 < /td>gt;gt;gt;')、3 行目の前に新しい行を追加します (複数行を同時に挿入できます)
    table.map(2) .add(-2, '')、新しい行を追加します3 行目の前の行
    table.map(0).add(2,'< ;/td>table.map(1).add(0,'< /td>gt ;gt;gt;')、インデックス 0 は、現在の行の前に新しい行を追加し、現在の行を削除することを意味します
    table.map(1).add( '')、最初のパラメータを省略します。これは特別な使用法です。 , どのオブジェクトが使用されているかに関係なく、新しい行が最後の行
    table.map(1,1).add(1,'New cell を決定します。
    function del(index){}このメソッドは兄弟ノードを削除するために使用されます。index は、このメソッドを呼び出すオブジェクトの位置を基準とした変位です。
    table.map( 1) .del()、インデックスを省略することは、それ自体を削除することを意味します。ここでの 2 行目の削除は、table.map(1).del(0)
    table.map(0).del(2) と同等です。現在の呼び出しに関連して、オブジェクトの後の 2 行目、ここでは 3 行目
    table.map(2).del(-2) を削除します。ここでは、現在の呼び出しオブジェクトの前の 2 行目を削除します。 、ここでは最初の行
    table .map(0,1).del([0,-1,1]) を削除します。index が配列の場合、指定されたインデックスの兄弟ノードが削除されます。今回は、どのオブジェクトが呼び出されるかは関係ありません。負のインデックスは最後の Counting から開始することを意味し、-1 は最後の Counting を意味します。ここでは最初、2 番目、最後の th
    table.map(0,1) を削除します。 del(0,-1)、パラメータが 2 つある場合は、区間の兄弟ノードを指定します。このとき、どのオブジェクトを呼び出すかは関係ありません。負のインデックスは最後から数えることを意味します。ここでは、最初から最後までの要素を削除します。サイズの順序に制限はありません。

    function getParent(){}
    呼び出し元オブジェクトの親オブジェクトに対応するネイティブ DOM オブジェクト ノードを取得します。table.map(0,1).getParent().tagName は tr です。
    function getHigher(){}
    呼び出し元オブジェクトの親オブジェクトを取得します。table.map(0,1).getHigher.getNode().tagName は tr です。 ルート オブジェクトと子孫オブジェクトが所有するメソッド
    function getNode(){}
    呼び出し元オブジェクトに対応するネイティブ DOM オブジェクト ノードを取得します。table.getNode().tagName はテーブル、table.map(0,1).getNode () 番目の
    function sizeOf(){}
    呼び出し元オブジェクトのサブオブジェクトの数を取得します。 table.sizeOf() は 3 です。これは、行が 3 つあることを意味します。
    function pos(){}
    すべての兄弟ノードにおける呼び出し元オブジェクトの位置を取得します。table.map(1).pos() は 1 です。
    function html(html){}
    呼び出し元のオブジェクトに対応するネイティブ DOM オブジェクトの innerHTML を取得します。パラメータが渡された場合は、その innerHTML 属性に値を割り当てます。読み取り専用オブジェクト innerHTML に値を割り当てます)
    関数 attr(html){}
    呼び出し元のオブジェクトに対応するネイティブ DOM オブジェクトの innerHTML を取得します。パラメータが渡された場合は、対応する属性に値を割り当てます (まだ実装されていません)。
    function before(index,html){}
    呼び出し元オブジェクトの指定されたサブオブジェクトの前にノードを追加します。index は相対的な変位です。
    table.before(1 ,'') という行を追加します。
    table.map (1 ,2,0).before(-1,'
  • 新しい li ノード
  • ')、最後の li の前に新しい li を追加します (インデックスは負の数は最後から数えることを意味し、-1 は最後を意味します)
    table.before('< /td> ;')、最初のパラメータを省略すると、最初のサブオブジェクトの前に新しいノードが追加されることになります。
    function append(index,html){}
    呼び出し元オブジェクトの指定されたサブオブジェクトの背後にノードを追加します。index は相対変位です。
    table.append(1,' gt;
    gt;gt; gt;
    table の後に行を追加します.map(1 ,2,0).append(-1,'
  • 新しい li ノード
  • ')、最後の li (インデックス) の後に新しい li を追加します。負の数は最後から数えることを意味し、-1 は最後を意味します)
    table.append(' ')、最初のパラメータを省略すると、最初のサブオブジェクトの後に新しいノードを追加することになります。
    function replace(index,html){}
    呼び出し元オブジェクトの指定されたサブオブジェクトに対応するネイティブ DOM ノードを、HTML によって生成されたノードに置き換えます。インデックスは相対ディスプレイスメントです。 🎜>table.replace( 2,'改行'), add新しい行を使用して、2 行目を置き換えます
    table.replace(-1,'New line< /td> ;')、新しい行を追加し、最後の行をその行に置き換えます (負のインデックスは最後から数えることを意味し、-1 は最後の行を意味します)
    function clean(index){}このメソッドは、兄弟ノードを削除するために使用されます。Index は、このメソッドを呼び出すオブジェクトの位置を基準とした変位です。 ()、インデックスの省略は、最初のサブオブジェクトの削除を意味します。ここでの最初の行の削除は、table.map(1).del(0)
    table.clean(2) と同じです。ここでは、3 行目の削除を意味します。 🎜>table.clean (-2)、ここでは最後の行を削除することを意味します
    table.map(0).clean([0,-1,1])、index が配列の場合、そのサブオブジェクト指定されたインデックスが削除され、インデックスが負の数の場合は最後から数えることを意味し、-1 は最後のものを意味します。ここでは最初、2 番目、最後の th
    table.map(0).clean(0,-) を削除します。 1) パラメータが 2 つある場合は、指定された範囲のサブオブジェクトを削除することを意味します。-1 は、最初から最後の要素を削除することを意味します。最初のパラメータとして使用できます。サイズオーダーに制限はありません


    新しいツリーのルート ノードが table で、その子ノードが tbody/thead/tfoot の場合、これらのノードを頻繁に操作するのではなく、tr を直接操作するため、わずかに許可されたスルーを作成しました。これらのノードの処理。もちろん、tbody を操作したい場合は、['tbody thead tfoot', 'tr', 'td'] のようにパラメータを渡すことができます。そのうちの 1 つだけを取得したい場合は、['tbody' , 'tr', 'td ']; tr を直接取得する場合は、['tr','td'] を実行すると、tbody/thead/tfoot 内のすべての tr に対して新しいオブジェクトが生成されます。 >
  • 結論: 考えてみれば、このようなプラグインがあれば、ノードの操作は簡単になります。前述したノード操作の 3 つの主要な問題は解決されます。また、このプラグインはロジックとは一切関係がないので、手に入れたらすぐに使用することができ、必要に応じて拡張することもできます。いつか開発プロセスがジグソーパズルのようになったら、開発したプラグインを組み合わせてプロジェクトが出来上がると想像してみてください。結果は期待したほど良くないかもしれませんが、この方向に進むと、イベントがますますシンプルになることは避けられません。記事が長くなってしまったので、ソースコード部分については次回記事を公開するときに詳しく説明します。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。