uni-app 条件编译解决跨端兼容问题
<p>https://uniapp.dcloud.io/platform</p><h2 id="跨端兼容">跨端兼容</h2>
<p>uni-app 已将常用的组件、JS API 封装到框架中,开发者按照 uni-app 规范开发即可保证多平台兼容,大部分业务均可直接满足。</p>
<p>但每个平台有自己的一些特性,因此会存在一些无法跨平台的情况。</p>
<ul>
<li>大量写 if else,会造成代码执行性能低下和管理混乱。</li>
<li>编译到不同的工程后二次修改,会让后续升级变的很麻烦。</li>
</ul>
<p>在 C 语言中,通过 #ifdef、#ifndef 的方式,为 windows、mac 等不同 os 编译不同的代码。 <code>uni-app</code> 参考这个思路,为 <code>uni-app</code> 提供了条件编译手段,在一个工程里优雅的完成了平台个性化实现。</p>
<h2 id="条件编译">条件编译</h2>
<p>条件编译是用特殊的注释作为标记,在编译时根据这些特殊的注释,将注释里面的代码编译到不同平台。</p>
<p><strong>写法:</strong>以 #ifdef 或 #ifndef 加 <strong>%PLATFORM%</strong> 开头,以 #endif 结尾。</p>
<ul>
<li>#ifdef:if defined 仅在某平台存在</li>
<li>#ifndef:if not defined 除了某平台均存在</li>
<li><strong>%PLATFORM%</strong>:平台名称</li>
</ul>
<table>
<thead>
<tr>
<th>条件编译写法</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>#ifdef <strong>APP-PLUS</strong> 需条件编译的代码 #endif</td>
<td>仅出现在 App 平台下的代码</td>
</tr>
<tr>
<td>#ifndef <strong>H5</strong> 需条件编译的代码 #endif</td>
<td>除了 H5 平台,其它平台均存在的代码</td>
</tr>
<tr>
<td>#ifdef <strong>H5</strong> || <strong>MP-WEIXIN</strong> 需条件编译的代码 #endif</td>
<td>在 H5 平台或微信小程序平台存在的代码(这里只有||,不可能出现&&,因为没有交集)</td>
</tr>
</tbody>
</table>
<p><strong>%PLATFORM%</strong> <strong>可取值如下:</strong></p>
<table>
<thead>
<tr>
<th style="text-align: left">值</th>
<th style="text-align: left">平台</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left">APP-PLUS</td>
<td style="text-align: left">App</td>
</tr>
<tr>
<td style="text-align: left">APP-PLUS-NVUE或APP-NVUE</td>
<td style="text-align: left">App nvue</td>
</tr>
<tr>
<td style="text-align: left">H5</td>
<td style="text-align: left">H5</td>
</tr>
<tr>
<td style="text-align: left">MP-WEIXIN</td>
<td style="text-align: left">微信小程序</td>
</tr>
<tr>
<td style="text-align: left">MP-ALIPAY</td>
<td style="text-align: left">支付宝小程序</td>
</tr>
<tr>
<td style="text-align: left">MP-BAIDU</td>
<td style="text-align: left">百度小程序</td>
</tr>
<tr>
<td style="text-align: left">MP-TOUTIAO</td>
<td style="text-align: left">字节跳动小程序</td>
</tr>
<tr>
<td style="text-align: left">MP-QQ</td>
<td style="text-align: left">QQ小程序</td>
</tr>
<tr>
<td style="text-align: left">MP-360</td>
<td style="text-align: left">360小程序</td>
</tr>
<tr>
<td style="text-align: left">MP</td>
<td style="text-align: left">微信小程序/支付宝小程序/百度小程序/字节跳动小程序/QQ小程序/360小程序</td>
</tr>
<tr>
<td style="text-align: left">QUICKAPP-WEBVIEW</td>
<td style="text-align: left">快应用通用(包含联盟、华为)</td>
</tr>
<tr>
<td style="text-align: left">QUICKAPP-WEBVIEW-UNION</td>
<td style="text-align: left">快应用联盟</td>
</tr>
<tr>
<td style="text-align: left">QUICKAPP-WEBVIEW-HUAWEI</td>
<td style="text-align: left">快应用华为</td>
</tr>
</tbody>
</table>
<p><strong>支持的文件</strong></p>
<ul>
<li>.vue</li>
<li>.js</li>
<li>.css</li>
<li>pages.json</li>
<li>各预编译语言文件,如:.scss、.less、.stylus、.ts、.pug</li>
</ul>
<p><strong>注意:</strong></p>
<ul>
<li>条件编译是利用注释实现的,在不同语法里注释写法不一样,js使用 <code>// 注释</code>、css 使用 <code>/* 注释 */</code>、vue/nvue 模板里使用 <code><!-- 注释 --></code>;</li>
<li>条件编译APP-PLUS包含APP-NVUE和APP-VUE,APP-PLUS-NVUE和APP-NVUE没什么区别,为了简写后面出了APP-NVUE ;</li>
</ul>
<h3 id="api-的条件编译">API 的条件编译</h3>
<pre><code class="language-javascript">// #ifdef%PLATFORM%
平台特有的API实现
// #endif
</code></pre>
<p>示例,如下代码仅在 App 下出现:</p>
<p><img src="https://img2020.cnblogs.com/blog/1652001/202103/1652001-20210317162723525-1753821877.png" alt="img" loading="lazy"></p>
<p>示例,如下代码不会在 H5 平台上出现:</p>
<p><img src="https://img2020.cnblogs.com/blog/1652001/202103/1652001-20210317162723518-147650801.png" alt="img" loading="lazy"></p>
<p>除了支持单个平台的条件编译外,还支持<strong>多平台</strong>同时编译,使用 || 来分隔平台名称。</p>
<p>示例,如下代码会在 App 和 H5 平台上出现:</p>
<p><img src="https://img2020.cnblogs.com/blog/1652001/202103/1652001-20210317162723499-242863453.png" alt="img" loading="lazy"></p>
<h3 id="组件的条件编译">组件的条件编译</h3>
<pre><code class="language-html"><!--#ifdef%PLATFORM% -->
平台特有的组件
<!--#endif -->
</code></pre>
<p>示例,如下公众号关注组件仅会在微信小程序中出现:</p>
<pre><code class="language-html"><view>
<view>微信公众号关注组件</view>
<view>
<!-- uni-app未封装,但可直接使用微信原生的official-account组件-->
<!-- #ifdef MP-WEIXIN -->
<official-account></official-account>
<!-- #endif -->
</view>
</view>
</code></pre>
<h3 id="样式的条件编译">样式的条件编译</h3>
<pre><code class="language-css">/*#ifdef%PLATFORM%*/
平台特有样式
/*#endif*/
</code></pre>
<p><strong>注意:</strong> 样式的条件编译,无论是 css 还是 sass/scss/less/stylus 等预编译语言中,必须使用 <code>/*注释*/</code> 的写法。</p>
<p>正确写法</p>
<p><img src="https://img2020.cnblogs.com/blog/1652001/202103/1652001-20210317162723501-324447307.png" alt="img" loading="lazy"></p>
<p>错误写法</p>
<p><img src="https://img2020.cnblogs.com/blog/1652001/202103/1652001-20210317162723518-676403232.png" alt="img" loading="lazy"></p>
<h3 id="pagesjson-的条件编译">pages.json 的条件编译</h3>
<p>下面的页面,只有运行至 App 时才会编译进去。</p>
<p><img src="https://img2020.cnblogs.com/blog/1652001/202103/1652001-20210317162723499-1161933399.png" alt="img" loading="lazy"></p>
<p>不同平台下的特有功能,以及小程序平台的分包,都可以通过 pages.json 的条件编译来更好地实现。这样,就不会在其它平台产生多余的资源,进而减小包体积。</p>
<p>json的条件编译,如不同平台的key名称相同,cli项目下开发者自己安装的校验器会报错,需自行关闭这些校验器对json相同key的校验规则。如果使用HBuilderX的校验器,无需在意此问题,HBuilderX的语法校验器为此优化过。</p>
<h3 id="static-目录的条件编译">static 目录的条件编译</h3>
<p>在不同平台,引用的静态资源可能也存在差异,通过 static 的的条件编译可以解决此问题,static 目录下新建不同平台的专有目录(目录名称同 <code>%PLATFORM%</code> 值域,但字母均为小写),专有目录下的静态资源只有在特定平台才会编译进去。</p>
<p>如以下目录结构,<code>a.png</code> 只有在微信小程序平台才会编译进去,<code>b.png</code> 在所有平台都会被编译。</p>
<pre><code>┌─static
│├─mp-weixin
││└─a.png
│└─b.png
├─main.js
├─App.vue
├─manifest.json
└─pages.json
</code></pre>
<h3 id="整体目录条件编译">整体目录条件编译</h3>
<p>如果想把各平台的页面文件更彻底的分开,也可以在uni-app项目根目录创建<code>platforms</code>目录,然后在下面进一步创建<code>app-plus</code>、<code>mp-weixin</code>等子目录,存放不同平台的文件。</p>
<p><strong>注意</strong></p>
<ul>
<li><code>platforms</code>目录下只支持放置页面文件(即页面vue文件),如果需要对其他资源条件编译建议使用static 目录的条件编译</li>
</ul>
<h3 id="hbuilderx-支持">HBuilderX 支持</h3>
<p>HBuilderX 为 <code>uni-app</code> 的条件编译提供了丰富的支持:</p>
<p><strong>代码块支持</strong></p>
<p>在 HBuilderX 中开发 <code>uni-app</code> 时,通过输入 <strong>ifdef</strong> 可快速生成条件编译的代码片段</p>
<p><img src="https://img2020.cnblogs.com/blog/1652001/202103/1652001-20210317162723546-839007107.png" alt="img" loading="lazy"></p>
<p><strong>语法高亮</strong></p>
<p>在 HBuilderX 中对条件编译的代码注释部分提供了语法高亮,可分辨出写法是否正确,使得代码更加清晰(独立js文件需在编辑器右下角切换javascript es6+编辑器,独立css文件暂不支持高亮,但不高亮不影响使用)</p>
<p><img src="https://img2020.cnblogs.com/blog/1652001/202103/1652001-20210317162723531-1689509138.png" alt="img" loading="lazy"></p>
<p><strong>正确注释和快速选中</strong></p>
<p>在 HBuilderX 中,ctrl+alt+/ 即可生成正确注释(js:<code>// 注释</code>、css:<code>/* 注释 */</code>、vue/nvue模板: <code><!-- 注释 --></code>)。</p>
<p><img src="https://img2020.cnblogs.com/blog/1652001/202103/1652001-20210317162723519-1139666552.png" alt="img" loading="lazy"></p>
<p>点击 <strong>ifdef</strong> 或 <strong>endif</strong> 可快速选中条件编译部分;点击左侧的折叠图标,可折叠条件编译部分代码。</p>
<p><img src="https://img2020.cnblogs.com/blog/1652001/202103/1652001-20210317162723533-2064385248.png" alt="img" loading="lazy"></p>
<h3 id="注意">注意</h3>
<ul>
<li>Android 和 iOS 平台不支持通过条件编译来区分,如果需要区分 Android、iOS 平台,请通过调用 uni.getSystemInfo 来获取平台信息。支持<code>ifios</code>、<code>ifAndroid</code>代码块,可方便编写判断。</li>
<li>有些跨端工具可以提供js的条件编译或多态,但这对于实际开发远远不够。uni-app不止是处理js,任何代码都可以多端条件编译,才能真正解决实际项目的跨端问题。另外所谓多态在实际开发中会造成大量冗余代码,很不利于复用和维护。举例,微信小程序主题色是绿色,而百度支付宝小程序是蓝色,你的应用想分平台适配颜色,只有条件编译是代码量最低、最容易维护的。</li>
<li>有些公司的产品运营总是给不同平台提不同需求,但这不是拒绝uni-app的理由。关键在于项目里,复用的代码多还是个性的代码多,正常都是复用的代码多,所以仍然应该多端。而个性的代码放到不同平台的目录下,差异化维护。</li>
</ul>
<h2 id="使用示例">使用示例</h2>
<pre><code><template>
<view>
<!-- #ifdef H5 -->
<view>我希望只在h5页面中看见</view>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<view>我希望只在微信小程序页面中看见</view>
<!-- #endif -->
</view>
</template>
<script>
export default {
onLoad() {
// #ifdef H5
console.log('我希望h5中打印')
// #endif
// #ifdef MP-WEIXIN
console.log('我希望微信小程序中打印')
// #endif
}
}
</script>
<style>
/* h5中的样式 */
/* #ifdef H5 */
view {
color: hotpink;
}
/* #endif */
/* 微信小程序中的样式 */
/* #ifdef MP-WEIXIN */
view {
color: #0000FF;
}
/* #endif */
</style>
</code></pre>
<p>效果</p>
<p><img src="https://img2020.cnblogs.com/blog/1652001/202103/1652001-20210317162723570-1503009525.png" alt="image-20210317162636317" loading="lazy"></p>
<p><img src="https://img2020.cnblogs.com/blog/1652001/202103/1652001-20210317162723593-28501731.png" alt="image-20210317162657060" loading="lazy"></p><br><br>
来源:https://www.cnblogs.com/makalochen/p/14550140.html
頁:
[1]