最新weex已經(jīng)改為支持Vue,舊的代碼.we代碼隨著更新迭代也會(huì)替換掉坎炼。項(xiàng)目還在繼續(xù)推進(jìn)weex的使用愧膀,隨后會(huì)更新最新一些自己使用weex-vue的總結(jié)。
以下為舊版weex開(kāi)發(fā)流程:
因
公司的app大量采用 hybrid 開(kāi)發(fā)谣光。iOS 在使用UIWebView時(shí)會(huì)消耗大量系統(tǒng)資源檩淋。 WKWebVIew 會(huì)是一個(gè)很好的解決方案。但是公司前端資源緊缺萄金,讓前端人員給iOS端做適配成本太高蟀悦。
果
iOS端首先試用Weex。如果可以的話捡絮,不止可以替換原有的web界面熬芜,復(fù)用網(wǎng)頁(yè)接口。還可以開(kāi)發(fā)一些強(qiáng)排版的native界面福稳,成熟之后涎拉,安卓直接使用。
參考文檔
開(kāi)發(fā)環(huán)境
- macOS 10.12.1
- atom (安裝 language-weex 高亮)
- iTerm2
- homebrew
- brew install node //通過(guò)brew安裝node
- npm install -g weex-toolkit *//通過(guò)node安裝 weex-toolkit *
初始化工程
- 創(chuàng)建文件夾
$ mkdir bookcover
- 進(jìn)入
bookcover
,初始化Weex工程
weex init
得到以下文件
prompt: Project Name: (detail) bookcover
file: .gitignore created.
file: README.md created.
file: index.html created.
file: package.json created.
file: src/weex-bootstrap.we created.
file: webpack.config.js created.
* 安裝 package.json 中的依賴(lài)
``` npm install ```
` node_modules/` 會(huì)創(chuàng)建很多依賴(lài)文件
如果提示
`npm WARN babel-loader@6.2.5 requires a peer of babel-core@^6.0.0 but none was installed.
`
執(zhí)行以下命令
` npm install babel-core`
* 編譯項(xiàng)目
`npm run dev`
* 啟動(dòng)輕量服務(wù)器
`npm run serve`
打開(kāi)瀏覽器的圆,輸入http://127.0.0.1:8080, 就會(huì)看到這個(gè)項(xiàng)目的效果.
以上步驟鼓拧,一個(gè)weex 的基本項(xiàng)目已經(jīng)創(chuàng)建好了≡铰瑁看詳細(xì)講解季俩,可以看上邊的兩個(gè)鏈接和weex源碼。
### 開(kāi)始創(chuàng)建自己的 .we 文件
源碼都在 `src` 目錄下梅掠,現(xiàn)在已經(jīng)包含一個(gè)`weex-bootstrap.we` 文件酌住。
#### 查看源碼 (三部分)
打開(kāi)文件
`$ atom weex-bootstrap.we`
##### 布局 (View)
<template>
<div class="ct" style="height: {{ctHeight}}">
<image class="img" style="width: 400px; height: 400px;" src="{{img}}"></image>
<text style="font-size: 42;">Hello Weex!</text>
</div>
</template>
> template 是模板的意思,這樣創(chuàng)建.we 的模板阎抒,其他文件調(diào)用時(shí)酪我,使用文件名作為模板名字。 例如:`first.we`
// index.we
<template>
<div>
<first></first> // 模板名稱(chēng)
...
</div>
</template>
##### 樣式
<style>
.ct {
width: 750;
align-items: center;
justify-content: center;
}
.img {
margin-bottom: 20px;
}
</style>
##### 數(shù)據(jù)+交互 (ViewModel)
<script>
module.exports = {
** 數(shù)據(jù)部分 **
data: {
ctHeight: 800,
img: '//gw.alicdn.com/tps/i2/TB1DpsmMpXXXXabaXXX20ySQVXX-512-512.png_400x400.jpg'
},
** 邏輯 **
ready: function () {
this.ctHeight = this.$getConfig().env.deviceHeight
}
}
</script>
### 組件間通訊
[參考 Weex 組件通訊](http://alibaba.github.io/weex/cn/doc/syntax/comm.html)
##### 從子組件向父組件通信
// 子視圖代碼 發(fā)送事件
test: function () {
this._parent.$emit('notify', {a: 1})
}
// 父視圖代碼 監(jiān)聽(tīng)
this.$on('notify', function(event) {
}
`notify` 為父視圖方法
`{a: 1}` 傳給父視圖的參數(shù)
##### 從父組件向子組件通信
// 父視圖vm獲取子視圖且叁,然后觸發(fā) changeImage
test: function (e) {
this.$vm('sub').$emit(
'changeImage',
'https://gtms02.alicdn.com/tps/i2/TB1QHKjMXXXXXadXVXX20ySQVXX-512-512.png' )
}
// 父視圖監(jiān)聽(tīng) changeImage
方法
created: function() {
this.$on('changeImage', function (e) {
this.imageUrl = e.detail }.bind(this))
}
##### 子組件通訊
weex官網(wǎng)沒(méi)有寫(xiě)都哭,個(gè)人通過(guò)以下方法解決: `子視圖1 ` -> `父視圖` -> `子視圖2`
#### We 生命周期
Weex 視圖模型現(xiàn)在支持生命周期內(nèi)的鉤子函數(shù),這些鉤子函數(shù)能被寫(xiě)為組件選項(xiàng):
* init: 在視圖模型的構(gòu)造函數(shù)開(kāi)始調(diào)用時(shí)激活逞带;
* created: 當(dāng)視圖模型監(jiān)聽(tīng)默認(rèn)數(shù)據(jù)欺矫,但還未編譯模板時(shí)激活;
* ready: 當(dāng)視圖模型監(jiān)聽(tīng)默認(rèn)數(shù)據(jù)并且編譯模板生成虛擬DOM后被激活展氓。
#### 找節(jié)點(diǎn)
* 父找子節(jié)點(diǎn)
// index.we
<template>
<div>
<first id = 'goto-top'></first> // 模板名稱(chēng)
...
</div>
</template>
``` var el = this.$el('goto-top')```
* 父找子上下文
this.$vm('goto-top').setTitle('Updated')
* 子找父
```this._parent```
### 將 .we 文件打包成 .js
$ weex index.we -o .
得到 `index.js` 文件穆趴。
將`index.js` 導(dǎo)入 iOS工作區(qū)間。
### 實(shí)例
創(chuàng)建文件
├── module
│ ├── chapter.we
│ ├── header.we
│ ├── recommand.we
│ └── urls.js
├── src
│ ├── index.we
* `urls.js` 保存url地址
* `index.we` 為界面主入口
* 其他為子視圖
index.we
<template>
<scroller>
<header id='header_id' style="margin-top: 128; " title="你好"></header>
<text onclick='updateTitle' style="padding: 40;">點(diǎn)我試試</text>
<chapter id='lastChapter'></chapter>
<recommand></recommand>
</scroller>
</template>
<script>
require('module/header.we');
require('module/chapter.we');
require('module/recommand.we');
...
</script>
> 因?yàn)閕ndex.we 為主視圖带饱,沒(méi)有具體視圖的實(shí)現(xiàn)毡代,所以此處沒(méi)有<style> 標(biāo)簽阅羹。
視圖分為是三部分 `header`, `chapter`, `remmend` 。根視圖為`scrollview`教寂。
三部分各自請(qǐng)求自己需要說(shuō)的數(shù)據(jù)捏鱼,然后刷新視圖。
### 擴(kuò)展
#### 網(wǎng)絡(luò)請(qǐng)求 (參考)
created: function() {
// 獲取url
var url = apis.getHeaderUrl();
// 獲取當(dāng)前視圖 酪耕,在回調(diào)中使用this取不到子視圖导梆。
var self = this;
// 發(fā)送請(qǐng)求
stream.fetch({
method: 'POST',
url: url,
type: 'json',
body: 'bookId=0000&id=000×tamp=1481188025939&sign=000000000000'
}, function(res) {
try {
var result = res.data.state;
if (result == 200) {
var body = res.data.data;
self.initData(body);
modal.toast({
'message': 'header 請(qǐng)求成功',
'duration': 1
})
}else {
modal.toast({
'message': 'header 請(qǐng)求失敗',
'duration': 1
})
}
} catch(e) {
modal.toast({
'message': e,
'duration': 1
})
}
}, function(res){
})
},
### Weex 原理
分為**Server** 和 **客戶端** ,**服務(wù)器下發(fā)**
![weex-jsRender.png](http://upload-images.jianshu.io/upload_images/695270-57154d329ac937f7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
**weex 翻譯成native**
| weex| native|
|-------|-------|
| style, attribute | WXDomObject |
| div, text迂烁,scoller, List... | WXComponent |
| script| WXModule |
| .we| WXSDKInstance |
### iOS支持 Weex
#### 環(huán)境
* xcode 8.1
* cocoapods 1.1.1
#### 步驟
* 創(chuàng)建支持pod項(xiàng)目 , `FirstWeex`
編輯Podfile
pod SDWebImage
pod WeexSDK
* 創(chuàng)建圖片下載類(lèi)
`WXImgLoaderDefaultImpl:NSObject<WXImgLoaderProtocol, WXModuleProtocol>`
實(shí)現(xiàn) 看尼。iOS9之后記得配置info.plist 打開(kāi)http請(qǐng)求
-
(id<WXImageOperationProtocol>)downloadImageWithURL:(NSString *)url imageFrame:(CGRect)imageFrame userInfo:(NSDictionary *)userInfo completed:(void(^)(UIImage *image, NSError *error, BOOL finished))completedBlock
{
if ([url hasPrefix:@"http://"]) {
url = [@"http:" stringByAppendingString:url];
}
return (id<WXImageOperationProtocol>)[[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:url] options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) {} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (completedBlock) {
completedBlock(image, error, finished);
}
}];
}
* AppDelegate配置weex
-
(void)initWeex {
[WXAppConfiguration setAppGroup:@"Company"];
[WXAppConfiguration setAppName:@"projectName"];
[WXAppConfiguration setAppVersion:@"1.0"];[WXSDKEngine initSDKEnviroment];
[WXLog setLogLevel:WXLogLevelError];
// 圖片下載
[WXSDKEngine registerHandler:[WXImgLoaderDefaultImpl new] withProtocol:@protocol(WXImgLoaderProtocol)];
}
* 加載 ViewController視圖
-
(void)viewDidLoad {
[super viewDidLoad];// 加載weex 視圖
[self render];
} -
(void)render {
[_instance destroyInstance];_instance = [[WXSDKInstance alloc] init];
_instance.viewController = self;
_instance.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds));__weak typeof(self) weakSelf = self;
_instance.onCreate = ^(UIView * view) {
[weakSelf.view addSubview:view];
};
_instance.onFailed = ^(NSError *error) {
NSLog(@"render onFailed");};
_instance.renderFinish = ^(UIView *view) {
NSLog(@"render finish");
};NSURL * url = _url;
if (!url) {
url = [[NSBundle mainBundle] URLForResource:@"index" withExtension:@"js"];
}if (url) {
[_instance renderWithURL:url options:@{@"bundleUrl":url.relativeString} data:nil];
}
}
此時(shí)會(huì)在 ViewController創(chuàng)建的時(shí)候,weex界面也會(huì)顯示盟步。
其實(shí)weex的本質(zhì)也是在UIView藏斩,所以像native的視圖是一樣進(jìn)行操作。