How to use removeVnodes method in Playwright Internal

Best JavaScript code snippet using playwright-internal

Run Playwright Internal automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

2.diff.js

Source: 2.diff.js Github

copy
1const nodeOps = {
2  setTextContent(text) {
3    if (platform === "weex") {
4      node.parentNode.setAttr("value", text);
5    } else if (platform === "web") {
6      node.textContent = text;
7    }
8  },
9  parentNode() {
10    //......
11  },
12  removeChild() {
13    //......
14  },
15  nextSibling() {
16    //......
17  },
18  insertBefore() {
19    //......
20  },
21};
22// insert 用来在 parent 这个父节点下插入一个子节点,如果指定了 ref 则插入到 ref 这个子节点前面
23function insert(parent, elm, ref) {
24  if (parent) {
25    if (ref) {
26      if (ref.parentNode === parent) {
27        nodeOps.insertBefore(parent, elm, ref);
28      }
29    } else {
30      nodeOps.appendChild(parent, elm);
31    }
32  }
33}
34// createElm 用来新建一个节点, tag 存在创建一个标签节点,否则创建一个文本节点。
35function createElm(vnode, parentElm, refElm) {
36  if (vnode.tag) {
37    insert(parentElm, nodeOps.createElement(vnode.tag), refElm);
38  } else {
39    insert(parentElm, nodeOps.createTextNode(vnode.text), refElm);
40  }
41}
42// addVnodes 用来批量调用 createElm 新建节点。
43function addVnodes(parentElm, refElm, vnodes, startIdx, endIdx) {
44  for (; startIdx <= endIdx; ++startIdx) {
45    createElm(vnodes[startIdx], parentElm, refElm);
46  }
47}
48// removeNode 用来移除一个节点。
49function removeNode(el) {
50  const parent = nodeOps.parentNode(el);
51  if (parent) {
52    nodeOps.removeChild(parent, el);
53  }
54}
55// removeVnodes 会批量调用 removeNode 移除节点。
56function removeVnodes(parentElm, vnodes, startIdx, endIdx) {
57  for (; startIdx <= endIdx; ++startIdx) {
58    const ch = vnodes[startIdx];
59    if (ch) {
60      removeNode(ch.elm);
61    }
62  }
63}
64// diff 算法是通过同层的树节点进行比较而非对树进行逐层搜索遍历的方式
65// 所以时间复杂度只有 O(n),是一种相当高效的算法
66function patch(oldVnode, vnode, parentElm) {
67  if (!oldVnode) {
68    // 没有老节点,插入新节点
69    addVnodes(parentElm, null, vnode, 0, vnode.length - 1);
70  } else if (!vnode) {
71    // 没有新节点,删除老节点
72    removeVnodes(parentElm, oldVnode, 0, oldVnode.length - 1);
73  } else {
74    // 如果是同一个节点,patchVnode
75    if (sameVnode(oldVNode, vnode)) {
76      patchVnode(oldVNode, vnode);
77    } else {
78      // 不是一个节点,删除老节点,新增新节点
79      removeVnodes(parentElm, oldVnode, 0, oldVnode.length - 1);
80      addVnodes(parentElm, null, vnode, 0, vnode.length - 1);
81    }
82  }
83}
84// 什么情况下两个 VNode 会属于 sameVnode (相同的节点)呢?
85function sameVnode() {
86  return (
87    a.key === b.key &&
88    a.tag === b.tag &&
89    a.isComment === b.isComment &&
90    !!a.data === !!b.data &&
91    sameInputType(a, b)
92  );
93}
94function sameInputType(a, b) {
95  if (a.tag !== "input") return true;
96  let i;
97  const typeA = (i = a.data) && (i = i.attrs) && i.type;
98  const typeB = (i = b.data) && (i = i.attrs) && i.type;
99  return typeA === typeB;
100}
101/**
102 * 核心方法
103 * @param {*} oldVnode
104 * @param {*} vnode
105 * @returns
106 */
107function patchVnode(oldVnode, vnode) {
108  // 新老 VNode 节点相同的情况下,就不需要做任何改变了,直接 return 掉
109  if (oldVnode === vnode) {
110    return;
111  }
112  // 在当新老 VNode 节点都是 isStatic(静态的),并且 key 相同时,
113  // 只要将 componentInstance 与 elm 从老 VNode 节点“拿过来”即可。
114  // 这里的 isStatic 也就是前面提到过的「编译」的时候会将静态节点标记出来,这样就可以跳过比对的过程。
115  if (vnode.isStatic && oldVnode.isStatic && vnode.key === oldVnode.key) {
116    vnode.elm = oldVnode.elm;
117    vnode.componentInstance = oldVnode.componentInstance;
118    return;
119  }
120  const elm = (vnode.elm = oldVnode.elm);
121  const oldCh = oldVnode.children;
122  const ch = vnode.children;
123  // 当新 VNode 节点是文本节点的时候,直接用 setTextContent 来设置 text
124  if (vnode.text) {
125    nodeOps.setTextContent(elm, vnode.text);
126  } else {
127    // oldCh 与 ch 都存在且不相同时,使用 updateChildren 函数来更新子节点
128    if (oldCh && ch && oldCh !== ch) {
129      updateChildren(elm, oldCh, ch);
130    } else if (ch) {
131      // 如果只有 ch 存在的时候
132      // 如果老节点是文本节点则先将节点的文本清除
133      if (oldVnode.text) nodeOps.setTextContent(elm, "");
134      // 然后将 ch 批量插入到节点elm下。
135      addVnodes(elm, null, ch, 0, ch.length - 1);
136    } else if (oldCh) {
137      // 同理当只有 oldch 存在时,说明需要将老节点通过 removeVnodes 全部清除
138      removeVnodes(elm, oldCh, 0, oldCh.length - 1);
139    } else if (oldVnode.text) {
140      // 最后一种情况是当只有老节点是文本节点的时候,清除其节点文本内容。
141      nodeOps.setTextContent(elm, "");
142    }
143  }
144}
145
146function updateChildren(parentElm, oldCh, newCh) {
147  let oldStartIdx = 0;
148  let newStartIdx = 0;
149  let oldEndIdx = oldCh.length - 1;
150  let oldStartVnode = oldCh[0];
151  let oldEndVnode = oldCh[oldEndIdx];
152  let newEndIdx = newCh.length - 1;
153  let newStartVnode = newCh[0];
154  let newEndVnode = newCh[newEndIdx];
155  let oldKeyToIdx, idxInOld, elmToMove, refElm;
156
157  // while 循环,在这过程中,oldStartIdx、newStartIdx、oldEndIdx 以及 newEndIdx 会逐渐向中间靠拢
158  while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
159    if (!oldStartVnode) {
160      oldStartVnode = oldCh[++oldStartIdx];
161    } else if (!oldEndVnode) {
162      oldEndVnode = oldCh[--oldEndIdx];
163    } else if (sameVnode(oldStartVnode, newStartVnode)) {
164      patchVnode(oldStartVnode, newStartVnode);
165      oldStartVnode = oldCh[++oldStartIdx];
166      newStartVnode = newCh[++newStartIdx];
167    } else if (sameVnode(oldEndVnode, newEndVnode)) {
168      patchVnode(oldEndVnode, newEndVnode);
169      oldEndVnode = oldCh[--oldEndIdx];
170      newEndVnode = newCh[--newEndIdx];
171    } else if (sameVnode(oldStartVnode, newEndVnode)) {
172      patchVnode(oldStartVnode, newEndVnode);
173      nodeOps.insertBefore(
174        parentElm,
175        oldStartVnode.elm,
176        nodeOps.nextSibling(oldEndVnode.elm)
177      );
178      oldStartVnode = oldCh[++oldStartIdx];
179      newEndVnode = newCh[--newEndIdx];
180    } else if (sameVnode(oldEndVnode, newStartVnode)) {
181      patchVnode(oldEndVnode, newStartVnode);
182      nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm);
183      oldEndVnode = oldCh[--oldEndIdx];
184      newStartVnode = newCh[++newStartIdx];
185    } else {
186      let elmToMove = oldCh[idxInOld];
187      if (!oldKeyToIdx)
188        oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx);
189      idxInOld = newStartVnode.key ? oldKeyToIdx[newStartVnode.key] : null;
190      // 当前newStartVnode在old还未遍历完的项目中,是否存在
191      if (!idxInOld) {
192        createElm(newStartVnode, parentElm);
193        newStartVnode = newCh[++newStartIdx];
194      } else {
195        elmToMove = oldCh[idxInOld];
196        if (sameVnode(elmToMove, newStartVnode)) {
197          patchVnode(elmToMove, newStartVnode);
198          oldCh[idxInOld] = undefined;
199          nodeOps.insertBefore(parentElm, newStartVnode.elm, oldStartVnode.elm);
200          newStartVnode = newCh[++newStartIdx];
201        } else {
202          createElm(newStartVnode, parentElm);
203          newStartVnode = newCh[++newStartIdx];
204        }
205      }
206    }
207  }
208
209  // 当 while 循环结束以后,如果 oldStartIdx > oldEndIdx,说明老节点比对完了
210  // 但是新节点还有多的,需要将新节点插入到真实 DOM 中去,调用 addVnodes 将这些节点插入即可
211  if (oldStartIdx > oldEndIdx) {
212    refElm = newCh[newEndIdx + 1] ? newCh[newEndIdx + 1].elm : null;
213    addVnodes(parentElm, refElm, newCh, newStartIdx, newEndIdx);
214  } else if (newStartIdx > newEndIdx) {
215    // 如果满足 newStartIdx > newEndIdx 条件,说明新节点比对完了,老节点还有多
216    // 将这些无用的老节点通过 removeVnodes 批量删除即可。
217    removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx);
218  }
219}
220
221function createKeyToOldIdx(children, beginIdx, endIdx) {
222  let i, key;
223  const map = {};
224  for (i = beginIdx; i <= endIdx; ++i) {
225    key = children[i].key;
226    if (isDef(key)) map[key] = i;
227  }
228  return map;
229}
230
Full Screen

patch.js

Source: patch.js Github

copy
1/**
2 * patch 算法 同层比较
3 */
4
5
6function patch (oldVnode, vnode, parentElm) {
7    if (!oldVnode) {
8        addVnodes(parentElm, null, vnode, 0, vnode.length - 1);
9    } else if (!vnode) {
10        removeVnodes(parentElm, oldVnode, 0, oldVnode.length - 1);
11    } else {
12        if (sameVnode(oldVNode, vnode)) {
13            patchVnode(oldVNode, vnode);
14        } else {
15            removeVnodes(parentElm, oldVnode, 0, oldVnode.length - 1);
16            addVnodes(parentElm, null, vnode, 0, vnode.length - 1);
17        }
18    }
19}
20
21function addVnodes (parentElm, refElm, vnodes, startIdx, endIdx) {
22    for (; startIdx <= endIdx; ++startIdx) {
23        createElm(vnodes[startIdx], parentElm, refElm);
24    }
25}
26
27function createElm (vnode, parentElm, refElm) {
28    if (vnode.tag) {
29        insert(parentElm, nodeOps.createElement(vnode.tag), refElm);
30    } else {
31        insert(parentElm, nodeOps.createTextNode(vnode.text), refElm);
32    }
33}
34
35function removeVnodes (parentElm, vnodes, startIdx, endIdx) {
36    for (; startIdx <= endIdx; ++startIdx) {
37        const ch = vnodes[startIdx]
38        if (ch) {
39            removeNode(ch.elm);
40        }
41    }
42}
43
44function removeNode (el) {
45    const parent = nodeOps.parentNode(el);
46    if (parent) {
47        nodeOps.removeChild(parent, el);
48    }
49}
50
51function sameVnode () {
52    return (
53        a.key === b.key &&
54        a.tag === b.tag &&
55        a.isComment === b.isComment &&
56        (!!a.data) === (!!b.data) &&
57        sameInputType(a, b)
58    )
59}
60
61function sameInputType (a, b) {
62    if (a.tag !== 'input') return true
63    let i
64    const typeA = (i = a.data) && (i = i.attrs) && i.type
65    const typeB = (i = b.data) && (i = i.attrs) && i.type
66    return typeA === typeB
67}
68
69function patchVnode (oldVnode, vnode) {
70    if (oldVnode === vnode) {
71        return;
72    }
73
74    if (vnode.isStatic && oldVnode.isStatic && vnode.key === oldVnode.key) {
75        vnode.elm = oldVnode.elm;
76        vnode.componentInstance = oldVnode.componentInstance;
77        return;
78    }
79
80    const elm = vnode.elm = oldVnode.elm;
81    const oldCh = oldVnode.children;
82    const ch = vnode.children;
83
84    if (vnode.text) {
85        nodeOps.setTextContent(elm, vnode.text);
86    } else {
87        if (oldCh && ch && (oldCh !== ch)) {
88            updateChildren(elm, oldCh, ch);
89        } else if (ch) {
90            if (oldVnode.text) nodeOps.setTextContent(elm, '');
91            addVnodes(elm, null, ch, 0, ch.length - 1);
92        } else if (oldCh) {
93            removeVnodes(elm, oldCh, 0, oldCh.length - 1)
94        } else if (oldVnode.text) {
95            nodeOps.setTextContent(elm, '')
96        }
97    }
98}
Full Screen

Accelerate Your Automation Test Cycles With LambdaTest

Leverage LambdaTest’s cloud-based platform to execute your automation tests in parallel and trim down your test execution time significantly. Your first 100 automation testing minutes are on us.

Try LambdaTest

Run JavaScript Tests on LambdaTest Cloud Grid

Execute automation tests with Playwright Internal on a cloud-based Grid of 3000+ real browsers and operating systems for both web and mobile applications.

Test now for Free
LambdaTestX

We use cookies to give you the best experience. Cookies help to provide a more personalized experience and relevant advertising for you, and web analytics for us. Learn More in our Cookies policy, Privacy & Terms of service

Allow Cookie
Sarah

I hope you find the best code examples for your project.

If you want to accelerate automated browser testing, try LambdaTest. Your first 100 automation testing minutes are FREE.

Sarah Elson (Product & Growth Lead)