<h1 id="articleHeader0">[新手坑] 01.<a href="http://www.js-code.com/tag/vue" title="Vue" target="_blank">Vue</a>模板内引入的组件样式覆盖失效</h1> <blockquote><p>作为一名刚接触<a href="http://www.js-code.com/tag/vue" title="Vue" target="_blank">Vue</a>的菜鸟, 开发过程中遇到一些小坑又很难搜索的到, 还是记录下来. 分享给有遇到过类似问题的人.</p></blockquote> <p><a href="http://www.js-code.com/tag/vue" title="浏览关于“Vue”的文章" target="_blank" class="tag_link">Vue</a>项目中假设用到<code>Vant.js</code>这个UI库, 具体引入组件啥的我就不详细说了, 直接看代码:</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="<template></p> <div class=&quot;login&quot;> <my-btn type=&quot;default&quot;>{{msg}}</my-btn> </div> <p></template></p> <p><script> import { Button } from 'vant' <a href="http://www.js-code.com/tag/export" title="export" target="_blank">export</a> default { name: 'App', components: { myBtn: Button }, data() { return { msg: 'whidy is poor XD' } } } </script></p> <style scoped> .van-button { width: 600px; } .van-button__text { font-size: 40px; } </style> <p>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs xml"><code class="vue"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name"><a href="http://www.js-code.com/tag/div" title="浏览关于“div”的文章" target="_blank" class="tag_link">div</a></span> <span class="hljs-attr">class</span>=<span class="hljs-string">"login"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">my-btn</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"default"</span>&gt;</span>{{msg}}<span class="hljs-tag">&lt;/<span class="hljs-name">my-btn</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"> <span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">'vant'</span> <span class="hljs-keyword"><a href="http://www.js-code.com/tag/export" title="浏览关于“export”的文章" target="_blank" class="tag_link">export</a></span> <span class="hljs-keyword">default</span> { <span class="hljs-attr">name</span>: <span class="hljs-string">'App'</span>, <span class="hljs-attr">components</span>: { <span class="hljs-attr">myBtn</span>: Button }, data() { <span class="hljs-keyword">return</span> { <span class="hljs-attr">msg</span>: <span class="hljs-string">'whidy is poor XD'</span> } } } </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">scoped</span>&gt;</span><span class="css"> <span class="hljs-selector-class">.van-button</span> { <span class="hljs-attribute">width</span>: <span class="hljs-number">600px</span>; } <span class="hljs-selector-class">.van-button__text</span> { <span class="hljs-attribute">font-size</span>: <span class="hljs-number">40px</span>; } </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></code></pre> <p>以上代码的写法不仔细看的话, 通过页面来看, <code>my-btn</code>组件实际上是Button, 而Vant的Button会生成类似如下:</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="<button data-v-0f984ad8=&quot;&quot; class=&quot;van-button van-button--default van-button--normal&quot;><!----><span class=&quot;van-button__text&quot;>whidy is poor XD</span></button>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="xml hljs"><code class="html" style="word-break: break-word; white-space: initial;"><span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">data-v-0f984ad8</span>=<span class="hljs-string">""</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"van-button van-button--default van-button--normal"</span>&gt;</span><span class="hljs-comment">&lt;!----&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"van-button__text"</span>&gt;</span>whidy is poor XD<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></code></pre> <p>其中的<code>van-button</code>的确宽度变成<code>600px</code>了, 而这个<code>van-button__text</code>却没有反应. 似乎一下子就傻眼了. 去掉<code>scoped</code>才有效果, 可是为啥要把这个作用域去了才行. 这个不符合我们需求, 因为这样会造成全局污染. 我仅仅是想要在这个页面中的按钮文本字体发生改变!</p> <h2 id="articleHeader1">问题原因</h2> <p><strong><code>scoped</code>是必不可少的, 但是我写了这个样式为何无法生效? 原因很简单, 因为当前样式仅适用于当前Vue模板的, 而模板中引入的其他组件其实是无法被渲染的.</strong></p> <h2 id="articleHeader2">解决方案</h2> <p>因此对于模板中引入第三方UI框架的样式如何改写, 正确方式是写一个优先级高于原组件的全局样式来覆盖默认样式, 比如</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="<my-btn type=&quot;default&quot; class=&quot;reset&quot;>{{msg}}</my-btn>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="xml hljs"><code class="html" style="word-break: break-word; white-space: initial;"><span class="hljs-tag">&lt;<span class="hljs-name">my-btn</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"default"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"reset"</span>&gt;</span>{{msg}}<span class="hljs-tag">&lt;/<span class="hljs-name">my-btn</span>&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="<template></p> <div class=&quot;login&quot;> <my-btn type=&quot;default&quot; class=&quot;reset&quot;>{{msg}}</my-btn> </div> <p></template></p> <p><script> import { Button } from 'vant' <a href="http://www.js-code.com/tag/export" title="export" target="_blank">export</a> default { name: 'App', components: { myBtn: Button }, data() { return { msg: 'whidy is poor XD' } } } </script></p> <style scoped> .van-button { width: 600px; } </style> <style> .reset .van-button__text { font-size: 40px; } </style> <p>" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs xml"><code class="vue"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"login"</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">my-btn</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"default"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"reset"</span>&gt;</span>{{msg}}<span class="hljs-tag">&lt;/<span class="hljs-name">my-btn</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span> <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript"> <span class="hljs-keyword">import</span> { Button } <span class="hljs-keyword">from</span> <span class="hljs-string">'vant'</span> <span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> { <span class="hljs-attr">name</span>: <span class="hljs-string">'App'</span>, <span class="hljs-attr">components</span>: { <span class="hljs-attr">myBtn</span>: Button }, data() { <span class="hljs-keyword">return</span> { <span class="hljs-attr">msg</span>: <span class="hljs-string">'whidy is poor XD'</span> } } } </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">scoped</span>&gt;</span><span class="css"> <span class="hljs-selector-class">.van-button</span> { <span class="hljs-attribute">width</span>: <span class="hljs-number">600px</span>; } </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span> <span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css"> <span class="hljs-selector-class">.reset</span> <span class="hljs-selector-class">.van-button__text</span> { <span class="hljs-attribute">font-size</span>: <span class="hljs-number">40px</span>; } </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></code></pre> <p>当然这里只是示例, 个人并不建议在模板上写多个style块, 所以我的做法一般还是在<code>assets</code>目录内新建一个例如<code>resetui.css</code>文件, 专门存放这些需要被重新修改的样式代码. 并且以组件的类名来进行维护, 比如上面一段, 最后处理好的代码应该是引入一个全局<code>resetui.css</code>, 并且该文件内的样式(我用了Post<a href="http://www.js-code.com/tag/css" title="CSS" target="_blank">CSS</a>)例如:</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=".login { .van-button__text { font-size: 40px; } }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="css hljs"><code class="css"><span class="hljs-selector-class">.login</span> { .van-button__text { <span class="hljs-attribute">font-size</span>: <span class="hljs-number">40px</span>; } }</code></pre> <p>这样就很好的解决了作用域和组件样式的问题了, 因此理解Vue模板和组件之间的作用域也是至关重要的~</p> <blockquote><p>其实这部分内容在官方文档有写, 不过大部分新手在阅读文档后, 并没有真正实践, 所以也就很容易忽略, 这里简单的做了个总结, 希望大家能够注意哦~</p> <p>我其实也很想能够做到, 当前模版内的scoped样式能够生效于当前模版内的所有组件的办法, 不过似乎是做不到的? 因此目前还是暂时按照上面的解决方案处理吧~</p> </blockquote> <p>参阅: <a href="https://cn.vuejs.org/v2/guide/class-and-style.html#%E7%94%A8%E5%9C%A8%E7%BB%84%E4%BB%B6%E4%B8%8A" rel="nofollow noreferrer" target="_blank">官方文档 - Class与Style绑定 - 用在组件上</a></p> <blockquote><p>我了更好的学习Vue-cli, 我在GitHub上建了一个<a href="https://github.com/whidy/vue-cli-mobile-study" rel="nofollow noreferrer" target="_blank">vue-cli-mobile-study</a>项目, 用于记录一些小技巧和坑, 其中记录过程中如果有问题, 也希望大家指出包涵~</p></blockquote> <p><em>下期: <a href="https://segmentfault.com/a/1190000014510238">02.Vue开发环境和生产环境样式不一致的问题</a></em></p>

本文固定链接: http://www.js-code.com/vue-js/vue-js_16650.html