<blockquote> <p>前提:这段时间将公司的几个用we写的weex页面用vue2.0进行了重构,客户端的weexsdk也更新到了<code>0.10.0</code>版本。这篇文章将会在前端视角写到一些新老版本之间有差异的地方。<a href="https://segmentfault.com/a/1190000007844330">we老版本的实践文章</a></p> <p>weex-vue-render v 0.10.0</p> <p><a href="http://www.js-code.com/tag/ios" title="ios" target="_blank">ios</a> weexSDK 0.10.0</p> <p><a href="http://www.js-code.com/tag/android" title="android" target="_blank">android</a> weexSDK 0.10.0</p> </blockquote> <h2 id="articleHeader0">编译vue文件</h2> <p>在we时代,对于业务代码<code>text.we</code>文件我们借助<code>weex-loader</code>以及webpack可以轻易的进行编译,得到最后需要的js。但是在vue时代,我们需要两个loader,<code>weex-loader</code>和<code>vue-loader</code>,对于公司接入来说我们不太会使用官方提供的脚手架工具,一般都是自己实现。这里容易产生混淆的是还有一个loader叫做<code>weex-vue-loader</code>,这个loader一般情况下对于开发者而言不需要手动调用。</p> <p>在build阶段或者在dev阶段,我们会使用<code>weex-loader</code>和<code>vue-loader</code>两个loader。</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="// native端使用的js weexWebpackConfig.module.loaders.push({ test: /.vue(?[^?]+)?$/, loader: require.resolve('weex-loader') }) weexWebpackConfig.output.filename = '[name].weex.min.js'" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-comment">// native端使用的js</span> weexWebpackConfig.module.loaders.push({ test: <span class="hljs-regexp">/.vue(?[^?]+)?$/</span>, loader: <span class="hljs-built_in">require</span>.resolve(<span class="hljs-string">'weex-loader'</span>) }) weexWebpackConfig.output.filename = <span class="hljs-string">'[name].weex.min.js'</span></code></pre> <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="// h5端使用的js vueWebpackConfig.module.loaders.push({ test: /.vue(?[^?]+)?$/, loader: require.resolve('vue-loader') }) vueWebpackConfig.output.filename = '[name].min.js'" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-comment">// h5端使用的js</span> vueWebpackConfig.module.loaders.push({ test: <span class="hljs-regexp">/.vue(?[^?]+)?$/</span>, loader: <span class="hljs-built_in">require</span>.resolve(<span class="hljs-string">'vue-loader'</span>) }) vueWebpackConfig.output.filename = <span class="hljs-string">'[name].min.js'</span></code></pre> <p>对于native端我们使用weex-loader进行编译vue文件,在weex-loader内部如果检测到该文件是vue则调用<code>weex-vue-loader</code>。对于H5端我们则使用vue官方提供的vue-loader进行vue的编译,同时我们对编译完成的文件名做区别,方便识别。</p> <p>对于大家自己实现脚手架很容易造成问题的一点是我们需要加入一段注释,让weexsdk识别这是vue。</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="var bannerPlugin = new webpackG.BannerPlugin( '// { &quot;framework&quot;: &quot;Vue&quot; }n', { raw: true } ) webpackConfig.plugins.push(bannerPlugin);" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs scala"><code><span class="hljs-keyword">var</span> bannerPlugin = <span class="hljs-keyword">new</span> webpackG.<span class="hljs-type">BannerPlugin</span>( '<span class="hljs-comment">// { "framework": "<a href="http://www.js-code.com/tag/vue" title="浏览关于“Vue”的文章" target="_blank" class="tag_link">Vue</a>" }n',</span> { raw: <span class="hljs-literal">true</span> } ) webpackConfig.plugins.push(bannerPlugin);</code></pre> <p><span class="img-wrap"><img data-src="/img/remote/1460000008571110?w=1758&amp;h=544" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="" title="" style="cursor: pointer;"></span></p> <p><a href="https://weex-project.io/cn/references/advanced/extend-jsfm.html" rel="nofollow noreferrer" target="_blank">来源:官方文档</a></p> <h2 id="articleHeader1">源码依赖管理</h2> <p>我们的业务是多页形式的,所以接入weex也非常方便。在每个页面引入该页面的由vue编译完后js文件。<code>vue</code>和<code>weex-vue-render</code>作为公共资源我们统一引入,因为我们需要结合native方定制一些错误收集等module,所以我们选择将vue、weex-vue-render以及定制化的module、component共同作为源码管理,统一打包成一个公共的文件在H5端引用。</p> <p>we时代我们也是这么做的,<a href="https://segmentfault.com/a/1190000007844330">详见</a>。vue时代在大体方向不变,在入口文件处做了微小的调整。</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="import Vue from 'vue' window.Vue = Vue /** * 注册component * */ // import TestComponent from './components/test/test.vue' // Vue.component('test-component', TestComponent) /** * 注册module * */ require('weex-vue-render') // shopBase import shopBase from './modules/shop-base' window.weex.registerModule('shopBase', shopBase) // shopModal import shopModal from './modules/shop-modal' window.weex.registerModule('shopModal', shopModal)" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-keyword">import</span> Vue <span class="hljs-keyword">from</span> <span class="hljs-string">'vue'</span> <span class="hljs-built_in">window</span>.Vue = Vue <span class="hljs-comment">/** * 注册component * */</span> <span class="hljs-comment">// import TestComponent from './components/test/test.vue'</span> <span class="hljs-comment">// Vue.component('test-component', TestComponent)</span> <span class="hljs-comment">/** * 注册module * */</span> <span class="hljs-built_in">require</span>(<span class="hljs-string">'weex-vue-render'</span>) <span class="hljs-comment">// shopBase</span> <span class="hljs-keyword">import</span> shopBase <span class="hljs-keyword">from</span> <span class="hljs-string">'./modules/shop-base'</span> <span class="hljs-built_in">window</span>.weex.registerModule(<span class="hljs-string">'shopBase'</span>, shopBase) <span class="hljs-comment">// shopModal</span> <span class="hljs-keyword">import</span> shopModal <span class="hljs-keyword">from</span> <span class="hljs-string">'./modules/shop-modal'</span> <span class="hljs-built_in">window</span>.weex.registerModule(<span class="hljs-string">'shopModal'</span>, shopModal)</code></pre> <p>我们可以看到相比以前component和module都由weex进行注册,而现在vue时代,我们的component将由<a href="http://www.js-code.com/tag/vue" title="Vue" target="_blank">Vue</a>进行注册,需要注意的是这里我将<a href="http://www.js-code.com/tag/vue" title="Vue" target="_blank">Vue</a>挂载到了<code>window</code>对象下,因为在各自页面的业务代码中,我们的入口js中需要实例化Vue,需要用到Vue对象。</p> <p>以及在注册module的时候我们的weex也是取自window对象下,<code>require('weex-vue-render')</code>这个步骤中会将weex挂载在window之下。</p> <p>具体的component编写现在已经完成变成了vue文件的编写,有vue经验的同学1秒上手。</p> <p>具体的module编写相比较以前也简化了很多,<a href="http://www.js-code.com/tag/export" title="export" target="_blank">export</a>一个包含module方法的对象,再调用<code>weex.registerModule</code>进行注册即可。<strong>值得注意的是在新官方文档上对<a href="http://www.js-code.com/tag/html5" title="html5" target="_blank">html5</a>的拓展部分没有讲到如何书写回调,回调的规则跟旧版还是一样的,下面的代码片段就是例子</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="const shopBase = { isOnline: function (callbackId) { const sender = this.sender; let hostname = window.location.hostname; let result = false; if (hostname.indexOf('showjoy.com') !== -1) { result = true; } sender.performCallback(callbackId, { data: result }) } } export default shopBase // another js window.weex.registerModule('shopBase', shopBase)" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs javascript"><code><span class="hljs-keyword"><a href="http://www.js-code.com/tag/const" title="浏览关于“const”的文章" target="_blank" class="tag_link">const</a></span> shopBase = { <span class="hljs-attr">isOnline</span>: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">callbackId</span>) </span>{ <span class="hljs-keyword">const</span> sender = <span class="hljs-keyword"><a href="http://www.js-code.com/tag/this" title="浏览关于“this”的文章" target="_blank" class="tag_link">this</a></span>.sender; <span class="hljs-keyword"><a href="http://www.js-code.com/tag/let" title="浏览关于“let”的文章" target="_blank" class="tag_link">let</a></span> hostname = <span class="hljs-built_in">window</span>.location.hostname; <span class="hljs-keyword">let</span> result = <span class="hljs-literal">false</span>; <span class="hljs-keyword">if</span> (hostname.indexOf(<span class="hljs-string">'showjoy.com'</span>) !== <span class="hljs-number">-1</span>) { result = <span class="hljs-literal">true</span>; } sender.performCallback(callbackId, { <span class="hljs-attr">data</span>: result }) } } <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> shopBase <span class="hljs-comment">// another js</span> <span class="hljs-built_in">window</span>.weex.registerModule(<span class="hljs-string">'shopBase'</span>, shopBase)</code></pre> <h2 id="articleHeader2">viewport的转变</h2> <blockquote> <p>这部分内容原理解释的有些绕,对viewport适配不了解的同学可以先看些我之前的文章<a href="http://lvdada.org/2016/01/28/viewport-and-flexibleJs/" rel="nofollow noreferrer" target="_blank">viewport-and-flexibleJs</a></p> </blockquote> <p>开发过we页面的同学应该了解,在之前的<code>weex-hmtl5</code>版本的weex中应该是没有对多屏幕视口适配做处理的,框架把视口适配的工作交给了手淘的<code><a href="http://www.js-code.com/tag/flex" title="flex" target="_blank">flex</a>ible.js</code>进行基于rem的视口适配。我们在H5端写页面的时候需要引入一段<code><a href="http://www.js-code.com/tag/flex" title="flex" target="_blank">flex</a>ible.js</code>脚本。</p> <p>基于vue2.0版本的weex舍弃了<code><a href="http://www.js-code.com/tag/flex" title="浏览关于“flex”的文章" target="_blank" class="tag_link">flex</a>ible.js</code>rem适配方案,改成了<code>750px</code>固定视口的方案。我们会看到不管在什么尺寸的手机屏幕上,<code>layout viewport</code>的值都为750px,所以我编写css代码的时候是无异的,都是以750为满屏宽进行代码的编写,区别仅在于现在要写度量单位<code>px</code>,而we时代是不需要的。</p> <div class="google-auto-placed ap_container" style="text-align: center; width: 100%; height: auto; clear: none;"><ins data-ad-format="auto" class="adsbygoogle adsbygoogle-noablate" data-ad-client="ca-pub-6330872677300335" data-adsbygoogle-status="done" style="display: block; margin: auto; background-color: transparent;"><ins id="aswift_4_expand" style="display: inline-table; border: none; height: 0px; margin: 0px; padding: 0px; position: relative; visibility: visible; width: 697px; background-color: transparent;"><ins id="aswift_4_anchor" style="display: block; border: none; height: 0px; margin: 0px; padding: 0px; position: relative; visibility: visible; width: 697px; background-color: transparent; overflow: hidden; opacity: 0;"><iframe width="697" height="175" frameborder="0" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true" onload="var i=this.id,s=window.google_iframe_oncopy,H=s&amp;&amp;s.handlers,h=H&amp;&amp;H[i],w=this.contentWindow,d;try{d=w.document}catch(e){}if(h&amp;&amp;d&amp;&amp;(!d.body||!d.body.firstChild)){if(h.call){setTimeout(h,0)}else if(h.match){try{h=s.upd(h,i)}catch(e){}w.location.replace(h)}}" id="aswift_4" name="aswift_4" style="left:0;position:absolute;top:0;border:0px;width:697px;height:175px;"></iframe></ins></ins></ins></div> <p>我在重构we页面的时候经历了<code>weex-vue-render</code>两个版本的迭代,一个是<code>v-0.2.0</code>还有一个就是<code>v-0.10.0</code>。</p> <p>这两个版本对<code>viewport</code>的处理也做了修改,我们在编写业务代码的时候也受到了一些由版本迭代带来的影响。</p> <p>在<code>weex-vue-render v-0.2.0</code>版本以及<code>weex-<a href="http://www.js-code.com/tag/html5" title="html5" target="_blank">html5</a>老weex</code>版本时我们在html文件中是可以不需要写<code>meta[name=viewport]</code>的,框架会自动帮我们计算得到页面需要的<code>viewport</code>信息。</p> <p><code>weex-<a href="http://www.js-code.com/tag/html5" title="浏览关于“html5”的文章" target="_blank" class="tag_link">html5</a></code>配合使用flexible适配多屏幕,这无需多言了。</p> <p><code>weex-vue-render v-0.2.0</code>的适配方式如下代码所示:</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="// 本文作者注释 // 此处默认值是750,由build时注入 const DEFAULT_VIEWPORT_WIDTH = process.env.VIEWPORT_WIDTH function parseViewportWidth (config) { let width = DEFAULT_VIEWPORT_WIDTH if (config &amp;&amp; config.width) { width = Number(config.width) || config.width } return width } export function setViewport (config = {}) { const doc = window.document if (doc) { const viewportWidth = parseViewportWidth(config) // set root font-size doc.documentElement.style.fontSize = viewportWidth / 10 + 'px' // 本文作者注释 // 重点语句 得到当前手机屏幕的宽度 const screenWidth = window.screen.width const scale = screenWidth / viewportWidth const contents = [ `width=${viewportWidth}`, `initial-scale=${scale}`, `maximum-scale=${scale}`, `minimum-scale=${scale}`, `user-scalable=no` ] let meta = doc.querySelector('meta[name=&quot;viewport&quot;]') if (!meta) { meta = doc.createElement('meta') meta.setAttribute('name', 'viewport') document.querySelector('head').appendChild(meta) } meta.setAttribute('content', contents.join(',')) } }" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs javascript"><code><span class="hljs-comment">// 本文作者注释</span> <span class="hljs-comment">// 此处默认值是750,由build时注入</span> <span class="hljs-keyword">const</span> DEFAULT_VIEWPORT_WIDTH = process.env.VIEWPORT_WIDTH <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseViewportWidth</span> (<span class="hljs-params">config</span>) </span>{ <span class="hljs-keyword">let</span> width = DEFAULT_VIEWPORT_WIDTH <span class="hljs-keyword">if</span> (config &amp;&amp; config.width) { width = <span class="hljs-built_in">Number</span>(config.width) || config.width } <span class="hljs-keyword">return</span> width } <span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">setViewport</span> (<span class="hljs-params">config = {}</span>) </span>{ <span class="hljs-keyword">const</span> doc = <span class="hljs-built_in">window</span>.document <span class="hljs-keyword">if</span> (doc) { <span class="hljs-keyword">const</span> viewportWidth = parseViewportWidth(config) <span class="hljs-comment">// set root font-size</span> doc.documentElement.style.fontSize = viewportWidth / <span class="hljs-number">10</span> + <span class="hljs-string">'px'</span> <span class="hljs-comment">// 本文作者注释 </span> <span class="hljs-comment">// 重点语句 得到当前手机屏幕的宽度</span> <span class="hljs-keyword">const</span> screenWidth = <span class="hljs-built_in">window</span>.screen.width <span class="hljs-keyword">const</span> scale = screenWidth / viewportWidth <span class="hljs-keyword">const</span> contents = [ <span class="hljs-string">`width=<span class="hljs-subst">${viewportWidth}</span>`</span>, <span class="hljs-string">`initial-scale=<span class="hljs-subst">${scale}</span>`</span>, <span class="hljs-string">`maximum-scale=<span class="hljs-subst">${scale}</span>`</span>, <span class="hljs-string">`minimum-scale=<span class="hljs-subst">${scale}</span>`</span>, <span class="hljs-string">`user-scalable=no`</span> ] <span class="hljs-keyword">let</span> meta = doc.querySelector(<span class="hljs-string">'meta[name="viewport"]'</span>) <span class="hljs-keyword">if</span> (!meta) { meta = doc.createElement(<span class="hljs-string">'meta'</span>) meta.setAttribute(<span class="hljs-string">'name'</span>, <span class="hljs-string">'viewport'</span>) <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'head'</span>).appendChild(meta) } meta.setAttribute(<span class="hljs-string">'content'</span>, contents.join(<span class="hljs-string">','</span>)) } }</code></pre> <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=" const screenWidth = window.screen.width " title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code style="word-break: break-word; white-space: initial;"> <span class="hljs-keyword">const</span> screenWidth = <span class="hljs-built_in">window</span>.screen.width </code></pre> <p>这条语句是这个适配脚本的重点之一,本意是为了拿到当前手机屏幕的<code>ideal viewport</code>理想视口,多数情况下<code>window.screen.width</code>是可以拿到屏幕的<code>ideal viewport</code>的,但是少部分安卓原生浏览器取到的值是有问题的。在正常情况iphone6下,这段脚本得到的值为:</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="`width=750`, `initial-scale=0.5`, `maximum-scale=0.5`, `minimum-scale=0.5`, `user-scalable=no`" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs typescript"><code><span class="hljs-string">`width=750`</span>, <span class="hljs-string">`initial-scale=0.5`</span>, <span class="hljs-string">`maximum-scale=0.5`</span>, <span class="hljs-string">`minimum-scale=0.5`</span>, <span class="hljs-string">`user-scalable=no`</span></code></pre> <p>但是在部分安卓手机下的浏览器会得到错误screenWidth从而得到错误的initial-scale,那么屏幕显示会出现问题。所以<code>weex-vue-render v-0.10.0</code>版本修改了这个脚本的实现,但是代价是我们必须要在html文件中添加一段<code>meta[name=viewport]</code>标签。</p> <p>标签的形式是:<code>&lt;meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"&gt;</code></p> <div class="google-auto-placed ap_container" style="text-align: center; width: 100%; height: auto; clear: none;"><ins data-ad-format="auto" class="adsbygoogle adsbygoogle-noablate" data-ad-client="ca-pub-6330872677300335" data-adsbygoogle-status="done" style="display: block; margin: auto; background-color: transparent;"><ins id="aswift_5_expand" style="display: inline-table; border: none; height: 0px; margin: 0px; padding: 0px; position: relative; visibility: visible; width: 697px; background-color: transparent;"><ins id="aswift_5_anchor" style="display: block; border: none; height: 0px; margin: 0px; padding: 0px; position: relative; visibility: visible; width: 697px; background-color: transparent; overflow: hidden; opacity: 0;"><iframe width="697" height="175" frameborder="0" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true" onload="var i=this.id,s=window.google_iframe_oncopy,H=s&amp;&amp;s.handlers,h=H&amp;&amp;H[i],w=this.contentWindow,d;try{d=w.document}catch(e){}if(h&amp;&amp;d&amp;&amp;(!d.body||!d.body.firstChild)){if(h.call){setTimeout(h,0)}else if(h.match){try{h=s.upd(h,i)}catch(e){}w.location.replace(h)}}" id="aswift_5" name="aswift_5" style="left:0;position:absolute;top:0;border:0px;width:697px;height:175px;"></iframe></ins></ins></ins></div> <p>需要添加这个标签没有在更新日志中体现,只在官网的<code>example</code>中修改了demo的实现,被这个坑绊到了。。。</p> <p>现在我们看一下在<code>weex-vue-render v-0.10.0</code>中是如何获取到设备的<code>ideal viewport</code>的,这也就解释了为何要在html中添加这个标签了。</p> <p><span class="img-wrap"><img data-src="/img/remote/1460000008571111?w=908&amp;h=420" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="" title="" style="cursor: pointer;"></span></p> <p>我们直接看源码修改的部分,这里将<code>window.screen.width</code>修改成了<code>document.documentElement.getBoundingClientRect().width</code></p> <p>直白话讲就是取得当前屏幕的html的宽度,而html的宽度则是由<code>&lt;meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"&gt;</code>标签的<code>width=device-width</code>决定的,结合起来讲就是这个标签将html的宽度设置成了device-width宽,而这个宽就是设备的<code>ideal viewport</code>的宽。而且这个值是永远正确的。这种方式计算得到的<code>viewport</code>在各种设备上都会以750px宽度呈现。</p> <p>另外如果我们是以源码依赖的方式而不是以<code>script</code>方式管理<code>weex-vue-render</code>的,0.10.0版本会有一个bug导致我们得到的viewport的值是undefined。</p> <p><span class="img-wrap"><img data-src="/img/remote/1460000008571112?w=728&amp;h=178" src="https://static.segmentfault.com/v-5cc2cd8e/global/img/squares.svg" alt="" title="" style="cursor: pointer;"></span></p> <p>原因在于<code>weex-vue-render</code>npm包中package.json的<code>main</code>字段指向了<code>"main": "src/render/vue/index.js",</code>源码,而源码中的viewport相关代码中含有<code><a href="http://www.js-code.com/tag/let" title="let" target="_blank">let</a> viewportWidth = process.env.VIEWPORT_WIDTH</code>环境变量,并没有文档说明我们在源码依赖<code>weex-vue-render</code>进行编译的时候需要给环境变量<code>process.env.VIEWPORT_WIDTH </code>设置750的值。所以编译出来的viewportWidth变量的值肯定是undefined。</p> <p>大家可以<code>npm i weex-vue-render@0.10.0</code>查看一下。</p> <p>解决办法一则将<code>main</code>入口指向weex-vue-render编译好的文件。方法二可以在我们自己管理源码的时候添加这个环境变量。</p> <h2 id="articleHeader3">0.10.0sdk支持相对地址并自动补全</h2> <p>在<code>0.4.0</code>版本的sdk中是不支持相对地址自动补全的,而我们前端同学在写业务逻辑时都是以相对地址的方式编写跳转路由或者api接口。</p> <p>比如一个api请求</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="stream.fetch({ method: 'GET', url: &quot;/api/shop, type: 'json' }, function (response) {})" title="" data-original-title="复制"></span> </div> </p></div> <pre class="hljs properties"><code><span class="hljs-attr">stream.fetch({</span> <span class="hljs-attr">method</span>: <span class="hljs-string">'GET',</span> <span class="hljs-attr">url</span>: <span class="hljs-string">"/api/shop,</span> <span class="hljs-attr">type</span>: <span class="hljs-string">'json'</span> <span class="hljs-meta">},</span> <span class="hljs-string">function (response) {})</span></code></pre> <p>h5端浏览器会自动拼接上当前域名的host,而native端拿到的只是这个相对地址请求。我司native方的做法是在网络请求之前手动拼接上需要的host域名,完成网络请求。</p> <p>但是native端的weexsdk从0.9.4版本开始支持不全相对地址。</p> <blockquote> <p>Support relative URL, which will resolve real URL by bundle's URL.</p> </blockquote> <p>但是比较坑的是与我们的业务场景不符合。因为sdk自动补全的host是根据js bundle的url进行的。</p> <p>比如我们的js bundle地址是<code>cdn1.xxx.com/js/weex.js</code>,但是业务里需要请求的接口的地址是<code>shop.m.xxx.com/api/getContent</code></p> <p>问题就是我们在<code>.vue</code>页面里写接口都是相对地址<code>/api/getContent</code>,这样的话weexSDK会根据bundle的host进行转换相对地址,变成了<code>cdn1.xxx.com/api/getContent</code>,导致接口请求404。</p> <p>所以这个时候需要native那边去写各自的handler和adapter,重写各自的网络请求,再在weexSDK中进行注册,这意味着需要在sdk进行不全之前native就先把url进行补全了,不把机会留给sdk进行处理。</p> <p><a href="https://github.com/alibaba/weex/issues/2795#issuecomment-284127044" rel="nofollow noreferrer" target="_blank">这个问题的issue</a></p> <h2 id="articleHeader4">小结</h2> <p>这还只是初步迁移到vue时代的尝试,但是基础已经打好,更多的业务已经可以接入进来了。未来还有许多在H5中考虑的内容需要重新在weex的视角下再进行考虑。</p> <blockquote> <p>本文来自尚妆前端团队<a href="http://weibo.com/u/2115840795" rel="nofollow noreferrer" target="_blank">南洋</a>,有什么需要讨论的欢迎找我,尤其是viewport相关的内容。</p> </blockquote>

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