寫在前面
Omi很適合大型復雜的Web頁面開發,例如一些Web在線工具的開發。但是制作這種簡單的QQ附近用戶列表Web頁,也不會有大炮哄蚊子的感覺。
項目開始之前,實現選擇一個腳手架。可以使用omi-cli快速創建項目腳手架。腳手架主要基於 Gulp + Webpack + Babel + BrowserSync 進行開發和部署。
Gulp用來串聯整個流程,Webpack + Babel讓你可以寫ES6和打包,BrowserSync用來幫你刷瀏覽器,不用F5了。
這里需要注意的是,BrowserSync會啟動localhost:3000導致你的AJAX請求跨域而無法拿到數據。
所以,要使用Fiddler並配置Extention:
目錄
目錄結構也是和Omi Github上的scaffolding一樣。
組件全放在component目錄,公共的工具庫放在common,其他資源文件放在asset里。
命令
開發
npm run dev
發布
npm run dist
開始寫碼
萬事具備,開始寫碼。先寫組件:
import Omi from 'omi'
class UserList extends Omi.Component {
constructor(data) {
super(data)
}
install() {
this.data.uin_info || (this.data.uin_info = [])
this.data.uin_info.forEach(user => {
this.prepareData(user)
})
}
prepareData(user){
user.desc_d = user.desc.split(" ")[0]
user.desc_t = user.desc.split(" ")[1]
user.isBoy = user.sex === "男"
user.qlogo = user.url.replace("http://", location.protocol + "//").replace(/&/g, "&")
if (user.profession_desc) {
user.hasProfession_desc = true
}
}
appendUsers (users) {
users.uin_info && users.uin_info.forEach(user =>{
this.prepareData(user)
this.data.uin_info.push(user)
})
this.update()
}
sendGift(uin, nick, qlogo) {
//送禮物並關閉webview,此處省略
//..
//..
}
render() {
return `
<div class="user_list">
{{#uin_info}}
<div class="item" onclick="sendGift('{{uin}}','{{nick}}','{{qlogo}}')">
<div class="qlogo">
<img style="width: 70px;" src="{{qlogo}}" />
</div>
<div class="main b1 bb">
<div class="nick">{{{nick}}}</div>
<div class="icons">
{{#isBoy}}<span class="boy_age"><img src="component/user_list/boy.png" alt="" /><span>{{age}}</span></span> {{/isBoy}}
{{^isBoy}}<span class="girl_age"><img src="component/user_list/girl.png" alt="" /><span>{{age}}</span></span> {{/isBoy}}
{{#hasProfession_desc}} <span class="profession"><span>{{profession_desc}}</span></span> {{/hasProfession_desc}}
</div>
<div class="action">{{{intro}}}</div>
</div>
<div class="distance_info">{{desc_d}} · {{desc_t}}</div>
</div>
{{/uin_info}}
<div style="text-align:center;font-size:13px;line-height:30px;height:30px;"><span class="loading"></span> 加載中...</div>
</div>
`
}
style() {
return `
.qlogo {
overflow: hidden;
width: 70px;
height: 70px;
-webkit-border-radius: 50%;
border-radius: 50%;
position: absolute;
top: 10px;
left: 12px;
}
...
...
..這里省略大量.....
...
...
.distance_info {
position: absolute;
top: 15px;
right: 9px;
color: #7B7B84;
font-size: 10px;
}
`
}
}
export default UserList
組件里面有5個方法:
- constructor 組件的構造函數,生命周期的一部分,其實在super上面和super調用下面可以對data做一些處理。super之上不能拿到this
- install 組件的初始化安裝,生命周期的一部分,這里也可以拿到用戶傳進的data進行處理
- prepareData 對數據進行一些處理來滿足模板的渲染
- appendUsers 新增數據,用來處理用戶向下滾動的load more 的行為的時候調用
- sendGift 送禮物,點擊每一項的時候會有送禮物的行為,業務相關,可以無視..
其他兩個方法的render和style用來生成組件的HTML和局部CSS,不再敘述。
render里面使用了mustache.js模板引擎;
如果使用omi.lite.js版本(不包含mustache.js模板引擎)的話,你也可以使用ES6 map去遍歷數據生成HTML,或者重寫 Omi.template去使用任意你喜歡的模板引擎,非常靈活方便。
這里友情提醒一下,如果使用webstorm的話,可以把js version設置成JSX Harmony或者ECMAScript 6,這樣才是寫ES6+的姿勢。
下面來看index.js:
import Root from './config.js'
import Omi from 'omi'
import UserList from '../component/user_list/index.js'
Omi.makeHTML('UserList', UserList)
class Main extends Omi.Component {
constructor(data) {
super(data)
}
installed() {
window.onscroll = () => this.loadMore()
this.requestData(data => this.list.appendUsers(data))
}
loadMore() {
const body = document.body,
html = document.documentElement,
height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight),
vp_height = window.innerHeight
if (height - document.body.scrollTop - vp_height < 200) {
this.requestData(data => this.list.appendUsers(data))
}
}
requestData(callback) {
if (Root.isDev) {
require.ensure([], ()=> {
callback(require('./mock_data.js').default)
})
}else{
//ajax 請求數據,這里省略
}
}
render() {
return `
<div class="main">
<UserList name="list" />
</div>`
}
}
Omi.render(new Main(),'body')
通過Omi.makeHTML('UserList', UserList)這句代碼,UserList變成了可以嵌套至render方法中的標簽。如:
render() {
return `
<div class="main">
<UserList name="list" />
</div>`
}
下面這行代碼,是監聽滾動,快滾動到底部的時候在loadMore里面會去請求。
window.onscroll = () => this.loadMore()
通過height - document.body.scrollTop - vp_height < 200判斷用戶快要滾動底部,滾動到底部有個加載更多的行為,即:
if (height - document.body.scrollTop - vp_height < 200) {
this.requestData(data => this.list.appendUsers(data))
}
requestData是去服務器請求分頁的數據,請求成功,會去調用this.list.appendUsers進行數據的添加。
慢着?this.list哪里來的?appendUsers又是哪里定義的方法?且看下面:
<UserList name="list" />
上面標記的name,讓你可以直接通過this.list訪問到UserList對象的實例,所以也就可以調用它的appendUsers方法!
再來看下數據模擬:
if (Root.isDev) {
require.ensure([], ()=> {
callback(require('./mock_data.js').default)
})
}
這里在dev環境下是mock數據,使用了require.ensure,這樣當你npm run dist的時候,mock的數據就不會被打包進js里了!!
最后
好了,就這么多,Omi讓代碼真心方便簡潔~~~
相關地址
招募計划
- Omi的Github地址https://github.com/AlloyTeam/omi
- 如果想體驗一下Omi框架,請點擊Omi Playground
- 如果想使用Omi框架,請閱讀 Omi使用文檔
- 如果想一起開發完善Omi框架,有更好的解決方案或者思路,請閱讀 從零一步步打造web組件化框架Omi
- 關於上面的兩類文檔,如果你想獲得更佳的閱讀體驗,可以訪問Docs Website
- 如果你懶得搭建項目腳手架,可以試試Scaffolding for Omi
- 如果你有Omi相關的問題可以New issue
- 如果想更加方便的交流關於Omi的一切可以加入QQ的Omi交流群(256426170)