脚本宝典收集整理的这篇文章主要介绍了

用 Vue 编写抽象组件

脚本宝典小编觉得挺不错的,现在分享给大家,也给大家做个参考,希望能帮助你少写一行代码,多一份安全和惬意。
<p><code></p> <p>看过 <a href="http://www.js-code.com/tag/vue" title="Vue" target="_blank">Vue</a> 源码的同学可以知道,<code>&lt;keep-alive&gt;</code>、<code>&lt;transition&gt;</code>、<code>&lt;transition-group&gt;</code>等组件<br />组件的实现是一个对象,注意它有一个属性 <code>abstract</code> 为 <code>true</code>,表明是它一个<code>抽象组件</code>。</p> <p><a href="http://www.js-code.com/tag/vue" title="Vue" target="_blank">Vue</a> 的文档没有提这个概念,在抽象组件的<strong>生命周期</strong>过程中,我们可以对包裹的子组件<strong>监听的事件进行拦截</strong>,也可以对子组件进行 <strong>Dom 操作</strong>,从而可以对我们需要的功能进行封装,而不需要关心子组件的具体实现。</p> <p>&lt;!-- more --&gt;</p> <p><strong>下面实现一个 <code>debounce</code> 组件,对子组件的 <code>click</code> 事件进行拦截</strong></p> <p>核心代码如下:</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<script> import {get, debounce, set} from 'loadsh';</p> <p><a href="http://www.js-code.com/tag/export" title="export" target="_blank">export</a> default { name: 'debounce',</p> <p> abstract: true, //标记为抽象组件</p> <p> render() { <a href="http://www.js-code.com/tag/let" title="let" target="_blank">let</a> v<a href="http://www.js-code.com/tag/node" title="node" target="_blank">node</a> = <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.$slots.default[0]; // 子组件的v<a href="http://www.js-code.com/tag/node" title="浏览关于“node”的文章" target="_blank" class="tag_link">node</a> if (vnode) { <a href="http://www.js-code.com/tag/let" title="let" target="_blank">let</a> event = get(vnode, `data.on.click`); // 子组件绑定的click事件 if (typeof event === 'function') { set(vnode, `data.on.click`, debounce(event, 1000)); } } return vnode; } }; </script>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs cs"><code class="vue">&lt;script&gt; import {<span class="hljs-keyword">get</span>, debounce, <span class="hljs-keyword">set</span>} <span class="hljs-keyword">from</span> <span class="hljs-string">'loadsh'</span>; <a href="http://www.js-code.com/tag/export" title="浏览关于“export”的文章" target="_blank" class="tag_link">export</a> <span class="hljs-keyword">default</span> { name: <span class="hljs-string">'debounce'</span>, <span class="hljs-keyword">abstract</span>: <span class="hljs-literal">true</span>, <span class="hljs-comment">//标记为抽象组件</span> render() { <span class="hljs-keyword"><a href="http://www.js-code.com/tag/let" title="浏览关于“let”的文章" target="_blank" class="tag_link">let</a></span> vnode = <span class="hljs-keyword"><a href="http://www.js-code.com/tag/this" title="浏览关于“this”的文章" target="_blank" class="tag_link">this</a></span>.$slots.<span class="hljs-keyword">default</span>[<span class="hljs-number">0</span>]; <span class="hljs-comment">// 子组件的vnode</span> <span class="hljs-keyword">if</span> (vnode) { <span class="hljs-keyword">let</span> <span class="hljs-keyword">event</span> = <span class="hljs-keyword">get</span>(vnode, `data.<span class="hljs-keyword">on</span>.click`); <span class="hljs-comment">// 子组件绑定的click事件</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> <span class="hljs-keyword">event</span> === <span class="hljs-string">'function'</span>) { <span class="hljs-keyword">set</span>(vnode, `data.<span class="hljs-keyword">on</span>.click`, debounce(<span class="hljs-keyword">event</span>, <span class="hljs-number">1000</span>)); } } <span class="hljs-keyword">return</span> vnode; } }; &lt;/script&gt;</code></pre> <p>使用</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<debounce><br /> <button @click=&quot;clickHandler&quot;>测试</button><br /> </debounce>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs xml"><code class="vue"><span class="hljs-tag">&lt;<span class="hljs-name">debounce</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"clickHandler"</span>&gt;</span>测试<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">debounce</span>&gt;</span></code></pre> <p>可以看到,按钮的 <code>click</code> 事件已经加上了去抖(debounce)操作。</p> <p><strong>我们可以进一步对 <code>debounce</code> 组件进行优化。</strong></p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<script> import {get, debounce, set} from '@/utils';</p> <p>export default { name: 'debounce',</p> <p> abstract: true, //标记为抽象组件</p> <p> props: { events: String, wait: { type: Number, default: 0 }, options: { type: Object, default() { return {}; } } },</p> <p> render() { let vnode = this.$slots.default[0]; // 子组件的vnode</p> <p> if (vnode &amp;&amp; this.events) { let eventList = this.events.split(','); eventList.forEach(eventName => { let event = get(vnode, `data.on[${eventName}]`); // 子组件绑定的click事件 if (typeof event === 'function') { /** * 加上debounce操作, 参数与 lodash 的debounce完全相同 */ set(vnode, `data.on[${eventName}]`, debounce(event, <a href="http://www.js-code.com/tag/this" title="this" target="_blank">this</a>.wait, this.options)); } }); } return vnode; } }; </script>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code class="vue">&lt;script&gt; <span class="hljs-keyword">import</span> {<span class="hljs-keyword">get</span>, debounce, <span class="hljs-keyword">set</span>} <span class="hljs-keyword">from</span> <span class="hljs-string">'@/utils'</span>; <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> { name: <span class="hljs-string">'debounce'</span>, <span class="hljs-keyword">abstract</span>: <span class="hljs-literal">true</span>, <span class="hljs-comment">//标记为抽象组件</span> props: { events: <span class="hljs-built_in">String</span>, wait: { <span class="hljs-keyword">type</span>: <span class="hljs-built_in">Number</span>, <span class="hljs-keyword">default</span>: <span class="hljs-number">0</span> }, options: { <span class="hljs-keyword">type</span>: <span class="hljs-built_in">Object</span>, <span class="hljs-keyword">default</span>() { <span class="hljs-keyword">return</span> {}; } } }, render() { <span class="hljs-keyword">let</span> vnode = <span class="hljs-keyword">this</span>.$slots.default[<span class="hljs-number">0</span>]; <span class="hljs-comment">// 子组件的vnode</span> <span class="hljs-keyword">if</span> (vnode &amp;&amp; <span class="hljs-keyword">this</span>.events) { <span class="hljs-keyword">let</span> eventList = <span class="hljs-keyword">this</span>.events.split(<span class="hljs-string">','</span>); eventList.forEach(<span class="hljs-function"><span class="hljs-params">eventName</span> =&gt;</span> { <span class="hljs-keyword">let</span> event = <span class="hljs-keyword">get</span>(vnode, <span class="hljs-string">`data.on[<span class="hljs-subst">${eventName}</span>]`</span>); <span class="hljs-comment">// 子组件绑定的click事件</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> event === <span class="hljs-string">'function'</span>) { <span class="hljs-comment">/** * 加上debounce操作, 参数与 lodash 的debounce完全相同 */</span> <span class="hljs-keyword">set</span>(vnode, <span class="hljs-string">`data.on[<span class="hljs-subst">${eventName}</span>]`</span>, debounce(event, <span class="hljs-keyword">this</span>.wait, <span class="hljs-keyword">this</span>.options)); } }); } <span class="hljs-keyword">return</span> vnode; } }; &lt;<span class="hljs-regexp">/script&gt;</span></code></pre> <p>使用</p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<debounce events=&quot;click&quot; :wait=&quot;250&quot; :options=&quot;{maxWait: 1000}&quot;><br /> <button @click=&quot;clickHandler&quot;>测试</button><br /> </debounce>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs xml"><code class="vue"><span class="hljs-tag">&lt;<span class="hljs-name">debounce</span> <span class="hljs-attr">events</span>=<span class="hljs-string">"click"</span> <span class="hljs-attr">:wait</span>=<span class="hljs-string">"250"</span> <span class="hljs-attr">:options</span>=<span class="hljs-string">"{maxWait: 1000}"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"clickHandler"</span>&gt;</span>测试<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">debounce</span>&gt;</span></code></pre> <p><strong>我们同样可以为输入框的 input 事件进行 debouce 操作</strong></p> <div class="widget-codetool" style="display:none;"> <div class="widget-codetool--inner"> <span class="selectCode code-tool" data-toggle="tooltip" data-placement="top" title="" data-original-title="全选"></span><br /> <span type="button" class="copyCode code-tool" data-toggle="tooltip" data-placement="top" data-clipboard-text="<debounce events=&quot;input&quot; :wait=&quot;250&quot; :options=&quot;{maxWait: 1000}&quot;><br /> <input @input=&quot;inputandler&quot; placeholder=&quot;输入关键字进行搜索&quot; /><br /> </debounce>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs ruby"><code class="vue">&lt;debounce events=<span class="hljs-string">"input"</span> <span class="hljs-symbol">:wait=<span class="hljs-string">"250"</span></span> <span class="hljs-symbol">:options=<span class="hljs-string">"{maxWait: 1000}"</span>&gt;</span> &lt;input @input=<span class="hljs-string">"inputandler"</span> placeholder=<span class="hljs-string">"输入关键字进行搜索"</span> /&gt; &lt;<span class="hljs-regexp">/debounce&gt;</span></code></pre> <blockquote><p>本文作者: <a>Shellming</a><br />本文链接: <a href="https://shellming.com/2019/05/06/vue-absract-components/" rel="nofollow noreferrer" target="_blank">https://shellming.com/2019/05/06/vue-absract-components/</a><br />版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!</p></blockquote> <p></code></p>

总结

以上是脚本宝典为你收集整理的

用 Vue 编写抽象组件

全部内容,希望文章能够帮你解决

用 Vue 编写抽象组件

所遇到的程序开发问题,欢迎加入QQ群277859234一起讨论学习。如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典网站推荐给程序员好友。 本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。

80%的人都看过