最近看了一篇很赞的文章,是讲 weex、react-native 和 JSPatch 之间的对比,作为一枚 iOS 程序猿,当然了,我使用过 react-native,JSPatch 也了解过(由于苹果爸爸禁止使用 hotfix,并没有派上用场),weex 当然也有必要去体验一下。
这里先贴下原文。
作为小白,最快了解和体验 weex 的办法,当然是寻求weex 官方文档的帮助。
Weex有一个在线编写代码的平台,可以先去感受一下,weex 使用 vue 语法开发,如果你以前写过 vue,那就太棒了。
如果想要在自己的本本上感觉一下,那么就需要安装 weex 的环境了。
说起来,weex 的使用感与 vue 是基本一致的,阿里同样提供了 weex 的脚手架,这对于新手真的很友好,项目的模板与 vue 也基本一致,同样是使用 webpack 来启动服务和进行 hot reload 的,对于我这个前端小白,里面的各种 loader 真的是让人头大(╯﹏╰)。
使用 weex-toolkit
weex-toolkit 是官方提供的一个脚手架命令行工具,你可以使用它进行 Weex 项目的创建,调试以及打包等功能。
node 的安装这里先略过,保证 node 的版本 >= 6
node -v # 查看 node 的版本 |
首先是安装 weex-toolkit
npm install -g weex-toolkit |
安装成功后,就可以愉快的去创建你的项目了
weex create weex-demo # 创建项目 |
顺利的话,你已经启动了你的 iOS 模拟器 ✌️
当然,你也许想要启动 weex 项目,自己修改点东西看看效果,你打开了项目的跟目录,观察了下 package.json 这个文件,项目目录下如果没有 node_modules 这个文件夹,首先需要
npm install # 安装依赖包 |
安装完成后,开始启动服务
npm run serve # 启动 serve 服务 |
可能你在启动服务的时候会遇到一个错误
Vue packages version mismatch: |
不匹配的对象是 vue
和 vue-template-compiler
。
这是由于 weex 要求他们完全匹配,但是你看了看你的 package.json,发现他们的版本号并没有什么问题,然后你把问题放到了 google 上,找到了很多同道中人,按照他们的方法试了个遍,发现依然没有解决问题,很难说这不是个悲伤的事实 ☹️
但是你并不是一无所获,有一个可能的原因 – 在这之前你安装了全局的 vue,然后你在终端敲下了
vue -v |
终端回应你了,他输出了 vue 的版本号,嗯,跟你的 package.json 里面并不一样…
现在有两个方式可以解决这个问题:
- 升级全局的 vue
- 删除掉全局环境下的 vue
为了长远考虑,当然是删除掉全局环境下的 vue 比较靠谱,哈哈~
全局的 vue 安装在当前用户的目录下
cd ~ |
找到 .vue 文件夹,删除他就可以了。
集成 WXDevtool
当然,如果为了简便,你可以直接使用 weex 提供的 playground 来体验或调试你的代码(在 app store 下载阿里爸爸 WeexPlayground),起初为了偷懒,我也是这么干的,新版的 dev tool 还是很给给力的,直接使用下面的命令就可以启动调试界面了,扫码开始调试吧,冲鸭~
weex debug |
虽然你满怀信心开始了你的调试之路,但是很不幸的是这条路总是容易断掉😭
看来还是自己集成 WXDevtool
比较靠谱哇!
weex 官方文档 - 集成 Devtools 到 iOS
使用 pod 集成
source https://github.com/CocoaPods/Specs.git, |
这里有个小插曲,也算是自己做的一点小贡献 😊
我直接集成的 WXDevtool
最新版本,按照文档集成,编译成功运行时总是内存崩溃,刚开始一直以为是自己哪里集成错误,反反复复试了很多遍,确定不是自己操作失误的话,那肯定就是代码哪里有问题了
崩溃的点在 WXDebugDomainController
类的 .m 文件的 line 88
,具体可以看我的题的 issue,现在最新版已经修复了这个问题了。
集成 WXDevtool
后,开启调试,模拟器会自动连接上,更方便,更快速 ✌️
但是最近在开启调试后页面直接白屏了,断点调试已经拿到页面数据了,还待进一步的研究…
使用 navigator 跳转页面
navigator
是 weex 提供的一个页面跳转模块,跟 vue 里面的 router-view
不同的是,他会在一个新的 ViewController
里面渲染页面,即 WeexSDK 里面封装的 WXBaseViewController
。
但是在使用 navigator
入栈的时候,push 的 url 需要针对不同的平台需要有不同的处理,幸好,我们可以根据 bundleUrl
获取不同平台的 baseUrl
:
getBaseUrl: function () { |
获取 baseUrl 后拼接上目标页面的 url 就可以了
getTargetUrl: function (url) { |
🌰🌰🌰
navigator.push({ |
/** |
最后说一下 navigator
不同页面传参的问题,最简单的方法就是将参数拼接到 url 的后面,然后在新的页面通过 this.$getConfig().bundleUrl
获取 url,解析参数:
created: function (event) { |
打包 js 文件
在使用 navigator
的时候,你会发现,如果要跳转到新页面,那么新页面也是需要打包成 js 文件的。
npm run dev
或者 npm run build
都可以对 .vue 文件打包,但是他们只打包了入口文件,在 webpack.common.conf.js 文件中,可以看到
const weexEntry = { |
这时,我们想要的 controllers 文件夹下面的 WebController.vue 并没有打包,navigator push 的 url 其实是一个 bundleUrl,需要独立打包成 js 文件才可以。
weex tool 提供了一个 命令来进行打包
weex compile src dist -d |
但是在使用这个命令的时候,只要我有导入其他组件,打包都会出错
Module not found: Error: Can't resolve '@/components/Channel' |
对于我这微薄的 webpack 认知,真的是 🤷♀️🤷♀️🤷♀️
weex 定义的命令路径为 /usr/local/lib/node_modules/weex-toolkit/node_modules/weex-builder/src
下,他定义的 entry file 是将所有的 .vue 都打包成入口文件
const entrys = {}; |
输出结果
{ |
既然知道是这样,那么我们就可以改写 webpack.common.conf.js
文件,具体的实现在 helper.js
中新增方法
const entrys = () => { |
同时
const weexEntry = helper.entrys(); |
这样就可以使用 npm run dev
或者 npm run build
打包啦~
但是注意这里我们使用脚手架生成的目录结构,默认的入口文件对应为 http://ip:port/index.js,对应 js 文件是 entry.js,同时 entry.js 也参与打包,所以修改我们的目录文件
|------ src |
因为每个 controller 之间是独立存在的,所以我在 index.js 里面定义个 mixin 在每个不同 ViewController 里面并不能共享使用
import baseMixins from '@/mixins/baseMixins'; |
顺便提一下,import
和 require
的用法
import
是 es6 的写法,对应 export default baseMixins;
require
是 es6 之前的写法,对应 module.exports = baseMixins;
写 mixin 的时候坑了好久 (;′⌒`)
关于启动 WebScoket 服务
weex run ios |
这个命令可以帮你启动 ws 服务,选择模拟器并编译运行 iOS 代码,这个命令下面最的工作还蛮多的,但是如果你只想启动 ws 服务怎么办呢,你可以修改这个命令,或者新增一个命令(机智如你,一定会选择新增命令的😎)
weex run 的命令在 /Users/xxx/.xtoolkit/node_modules/weexpack/lib/run
复制 ios.js 文件,修改为 hot.js
修改 hot.js
var runHot = function runHot(options) {
logger.info('npm run build');
utils.checkAndInstallForIosDeploy().then(utils.buildJS).then(function () {
return copyJsbundleAssets(process.cwd(), 'dist', 'platforms/ios/bundlejs/');
}).then(function () {
return passOptions(options);
}).then(prepareIOS).then(startHotReloadServer).then(registeFileWatcher).then(resolveConfig).catch(function (err) {
if (err) {
logger.error('Error:' + (err.stack || err));
exit(0);
}
});
};
module.exports = runHot;修改同级目录下的 index.js
;
var runAndroid = require('./android');
var runIOS = require('./ios');
var runWeb = require('./web');
var runHot = require('./hot'); // 新增
module.exports = {
runAndroid: runAndroid,
runIOS: runIOS,
runWeb: runWeb,
runHot: runHot // 新增
};修改 ../lib 目录下的 weexpack-run.js,添加命令
...
const {
runAndroid,
runIOS,
runWeb,
runHot
} = require('../lib/run');
...
function isValidPlatform(args) {
if (args && args.length) {
return args[0] === 'android' || args[0] === 'ios' || args[0] === 'web' || args[0] === 'hot'
}
return false
}
...
function run(platform, options) {
switch (platform) {
case 'android' : runAndroid(options); break;
case 'ios' : runIOS(options); break;
case 'web' : runWeb(options); break;
case 'hot' : runHot(options); break;
}
}
好了,现在你就可以使用 weex run hot
命令来开启你的 ws 服务了。
代码请戳这里 O(∩_∩)O~~