易、輕、快!超牛逼純JS前端框架——MithrilJS

--> -->

這裡面是純原生,沒有使用webpack之類的打包,所以引用了很多組件js,當然你也可以寫到一個裡面,但是那實在不好看也不好拓展。

使用了less,為了偷懶,你讓我在工程裡面使用原生CSS,臣妾真的做不到了。


less

less的內容就不做過多展示,這個有興趣在下方去源碼裡面看吧,這裡略過了。


js

大頭來了,我這裡會直接貼出代碼,然後在路由那裡說一下,為什麼我不多說呢,因為MithrilJS真的太簡單了(我會告訴你我懶得說麼)。。。

header.js

const Header = (function() {

return {

view(v) {

const titles = ['首頁', '分享', '設計', '繪畫', '攝影']

const hrefs = ['#!/', '#!/share']

const selectedIndex = v.attrs.selectedIndex

return m("header", [

m("h1", "KOOJEE"),

m('section.titles',

titles.map((title, index) => m('a', {class: 'title' + (selectedIndex === index ? ' selected' : ''), href: hrefs[index] || '#'}, titles[index])

)

),

])

}

}

})()

這裡使用了自運行函數,為了是避免變量名汙染。

組件就是個對象,組件DOM結構實在view這個屬性值下的一個函數返回,函數可攜帶vnode對象,用來傳參等等,獲取參數使用v.attrs。

其他就是常規內容,渲染了一個header標籤,裡面包了一個h1標籤,包了一個section.titles標籤,section.titles裡面根據titles數組生成了5個a.title標籤。

這就是header了。


footer.js

const Footer = (function() {

return {

view() {

return m(

'footer'

)

}

}

})()

目前沒東西,所以渲染了一個空的footer標籤用來佔位。


homepage.js

const Homepage = (function() {

const h2 = '最終選擇了生活……'

const h3 = '寧願向著遠方哭泣,不願望著當下詫異。'

let contentImgs = ['Bitmap1.png', 'Bitmap2.png', 'Bitmap3.png', 'Bitmap4.png']

let arts = [

{

img: 'Bitmap5.png',

main: '經歷',

desc: '我在東方等你,不濟那遠去的夕陽。',

},

{

img: 'Bitmap6.png',

main: '興趣',

desc: '給個遊戲,能躺半年。',

},

{

img: 'Bitmap7.png',

main: '性格',

desc: '熱辣似火,妖嬈弄人?不不不,就是呆萌。',

},

{

img: 'Bitmap8.png',

main: '態度',

desc: '你到底準備用什麼態度和姑奶奶說話?',

},

]

const Content = {

onbeforeremove(v) {

v.dom.classList.add("exit")

return new Promise(function(resolve) {

setTimeout(resolve, 500)

})

},

view() {

return m('main#homepage.fancy',

m('section.content-center', [

m('h2', h2),

m('h3', h3),

contentImgs.map((contentImg, index) => m('img', {class: 'img' + index, src: assetsPath + contentImg, alt: 'content-img'}))

])

)

}

}

return {

view(v) {

return [

m(Header, {selectedIndex: 0}),

m(Content),

m(Footer),

]

}

}

})()

因為將來要使用數據驅動,所以把數據提出去,方便後續服務器請求數據操作。

這裡使用了m函數的組件模式,如上例子中的:m(Header, {selectedIndex: 0}),就是homepage組件裡面包含了一個Header組件,並且給Header組件傳參了,這個參數的使用在上面Header組件那裡可以看到。

注意這裡有個內部的Content組件,這個是用來做動畫的,比如你頁面內路由切換時,為了看起來更舒服,可以做個過渡動畫,Homepage組件自帶fancy類的CSS,然後Homepage的Content組件在聲明週期onbeforeremove即將要消失的時候添加了一個exit類的CSS,具體兩個CSS如下:

.fancy {animation:fade-in 0.5s;}

@keyframes fade-in {

from {opacity:0;}

to {opacity:1;}

}

.exit {animation:fade-out 0.5s;}

@keyframes fade-out {

from {opacity:1;}

to {opacity:0;}

}

瞭解CSS的同學就知道是什麼動畫了,對,就是淡入與淡出,分別0.5s。

說到這裡,剛好順帶過一下MithrilJS的聲明週期,如下:

用法與view一樣,放在對象的屬性上,對應值是函數,都可以獲取vnode。

  1. oninit
  2. 初始化時候,方便放一些準備用的數據,或者用來網絡請求。此時可以拿到vnode,但是不一定拿得到真實DOM,所以這裡不推薦進行相關的DOM操作,比如:vnode.dom。
  3. oncreate
  4. 創建成功,此時可以拿到真實DOM了。
  5. onupdate
  6. DOM渲染刷新後。業務有刷新變動數據時候使用。
  7. onbeforeremove
  8. DOM銷燬前。常用,比如我們的離開動畫。
  9. onremove
  10. DOM銷燬後。一樣不建議進行真實DOM操作,用來銷燬垃圾數據可以使用。
  11. onbeforeupdate
  12. DOM渲染刷新前。業務有刷新變動數據時候使用。

share.js

const Share = (function() {

let bannerSrc = 'https://wbroom-blog.oss-cn-hangzhou.aliyuncs.com/public/assets/share-bannre.png'

const Content = {

onbeforeremove(v) {

v.dom.classList.add("exit")

return new Promise(function(resolve) {

setTimeout(resolve, 500)

})

},

view() {

return m('main#share.fancy', [

m(`img.share-banner[class="lazy" src="//p2.ttnews.xyz/loading.gif" data-original=${bannerSrc}]`),

m('section.arts',

[1,1,1,1,1,1].map((item, index) => m('figure.art', [

m(`img.head[alt=${index}]`, {src: 'https://wbroom-blog.oss-cn-hangzhou.aliyuncs.com/public/assets/Bitmap1.png'}),

m('figcaption.main', '別看,看也沒博文。'),

m('span.time', '耶穌生日的那天'),

m('section.ctrl', [

m('span', '點贊(1000)'),

m('span', '評論(1000)'),

m('span', '瀏覽(100000)')

])

]))

),

m('section.pagination', '頁碼(待處理)'),

])

}

}

return {

view(v) {

return[

m(Header, {selectedIndex: 1}),

m(Content),

m(Footer),

]

}

}

})()

與homepage大同小異,只是堆頁面,放置一些圖片,頁碼也還沒做~

注意,一樣要設置進場動畫與離場動畫。


app.js

const rootPath = 'https://wbroom-blog.oss-cn-hangzhou.aliyuncs.com/'

const publicPath = rootPath + "public/"

const assetsPath = publicPath + "assets/"

m.route(document.body, '/', {

"/": Homepage,

'/share': Share,

})

這個就是常說的入口js了,由於存在JS對象的依賴關係,所以上面的組件不得不先加載,然後最後加載入口js。

第一:做一些全局的數據,比如本項目裡面需要用到的圖片資源basic路徑等。

第二:路由的簡單配置。

注意,MithrilJS沒有類似Vue的router-view這種組件,它還是建議把組件配到大組件裡面,這個缺點就是如果業務的路由組件非常深入,就相對麻煩,但是優點還是簡單!

這裡配置根路徑地址就是Homepage組件,當路由切換到share時候,就是Share組件顯示了。

同樣的,MithrilJS的路由標記像這樣:#!/share,默認是使用#!,當然,你可以通過類似m.route.prefix("#")來修改路由標記,但是個人覺得意義不大。起碼別人逛你網站的時候,懂行的一眼就看出來你用的是MithrilJS寫的頁面,恩,厲害!


到最後,index.html解析所有的內容後,就渲染出文章開頭的頁面了,點擊切換時候還有淡入淡出的效果(上面的鏈接看不到,因為Vue版本我還沒加路……)。


OK,簡單,快速,小巧的一個牛逼純JS框架MithrilJS,帶你們走了一遍簡單的。

MithrilJS當然也是支持ES6,以及JSX的,本人不是很喜歡JSX的寫法,所以採用了原生的,而要用以上兩個,都需要去配置下webpack,這裡不做過多介紹了。

如果想看源碼,請到下面的GitHub源碼裡面,找到mi分支即可,默認master分支是Vue版本哦。


項目源碼:Github:https://github.com/ZweiZhao/WBRoom


喜歡我的文章,請關注一波啊,定期更新技術文章,滿滿的都是乾貨!


分享到:


相關文章: