這個一樣是寫博客的產出,以前在寫博客的時候,瞎弄了一個模板引擎,當時就想以後把他優化一下,把 Vue
響應式原理放進去,弄成一個小的能夠用來減小我寫博客前端代碼的組件化的」框架「,因而我就來填坑了。這個只是本身用來學習 Vue2.0
響應式原理的一個小項目,代碼的實現可能很初級,有些地方寫的會比較差,請見諒。這篇文章先看下,最終實現的框架的成果。javascript
項目源碼:傳送門 實現效果:個人博客就是用這個小框架改造的html
實現的這個小框架,是一個雙向綁定的組件化的小框架,有跨組件通訊,組件屬性,事件綁定,數據綁定,列表渲染等功能,可是也存在不少缺陷的,好比沒實現對 html
中的模板綁定、組件屬性沒有聲明等。只是一個學習的項目,勿怪哈,但願能給大家帶來幫助。前端
仿照了vue
的寫法,實現了一個組件的定義和註冊,並無全局和局部組件的區分,都是全局組件。vue
import MVue from '@/components/index'
const tagsLink = {
name: 'tags-link', // 組件名,必需
template: 'a[href="javascript:;]@click.stop=navTag:tag@{$tag.name$}', // 模板,必需
data () { // 組件內部的響應式數據
return {
tag:{
name: '標籤'
}
}
},
created() { // 實例 mvue 建立的回調
this.navTag(this.tag)
this.$event.emmit('load-more') //跨組件通訊的事件總線,觸發事件
},
methods: { // 組件內部方法
navTag(tag) {
const target = './tag.html'
this.$router.navTo(target, { //簡單的路由
id: tag.tagId
})
}
}
}
MVue.Component(tagsLink) //註冊組件
複製代碼
定義了組件以後要在html
中使用的話,須要定義一個根實例,一個完整的使用示例,以下代碼書寫java
<div id="app">
<article-list :articles="articles"></article-list> // 組件書寫,和屬性傳遞,只有這個寫法,沒有在HTML中作響應式的綁定語法
<load-more :pages="pages"></load-more>
</div>
複製代碼
import MVue from '@/components/index'
import router from '@/utils/router.js'
import articleList from './article-list.js'
import loadMore from './load-more.js'
MVue.router = router // 把路由方法掛上去
// 註冊使用組件
MVue.Component(articleList)
MVue.Component(loadMore)
const mVue = new MVue({
el: '#app', //
data: {
pages: {
text: '獲取更多',
currentPage: 0,
pageSize: 5,
more: true
},
articles: []
},
created() {
this.getArticles()
this.$event.on('load-more', this.getArticles, this) //註冊自定義事件
},
methods: {
async getArticles() {
if (!this.pages.more) {
return
}
this.pages.currentPage++
const res = await getArticleList(
this.pages.currentPage,
this.pages.pageSize,
true,
{ articleState: 1 }
)
if (res.flag) {
if (res.data.length < this.pages.pageSize) {
this.pages.more = false
this.pages.text = '沒有更多了'
}
this.articles.push(...res.data)
}
},
}
})
//組件渲染,建立dom 把組件添加進DOM樹
mVue.render(() => {
document.querySelector('#mask').style.display = 'none'
})
複製代碼
這個和我以前寫的小模板引擎是相似的webpack
div[class="box]{hahaha}
表示 <div class="box">hahaha</div>
[]
屬性 =》 寫法:[class="box,id="box]
{}
文本 =》 寫法: {hahaha}
h6[class="font-$regular$]{ 建立時間:$article.createtime$ -- 修改時間:$article.modifiedtime:time$}
$data$
兩個$
之間寫上組件實例定義的變量名或者父組件傳入的變量:
以後的爲組件實例定義的方法,會將函數返回結果填充載$
之間a@click.stop=nav:article@[href="javascript:;,class="title]
@
之間爲組件綁定的事件部分事件名.stop=方法名:參數1:參數2
innerHtml
的使用:div[class="markdown-body,style="padding: 0;]^article.abstract:markdown^
^
之間是對應的html
綁定部分(會忽略{}
)=》變量名:方法名
div.innerHtml = 返回值
article-item[:article="item]
[:article="item]
表示 :組件的屬性名="當前組件的變量名
,屬性名綁定後能夠在組件中直接使用該變量名(沒有聲明),屬性能夠層層傳div>(a+article-item)
>
父子關係+
兄弟關係()
優先運算同一層級html
中使用// html中使用
<div id="app">
<tags-list></tags-list> // 組件書寫 </div>
/******** 組件定義 ********/
//父組件
{
name: 'tags-list',
template: 'div>tags-link%item in tags%[:tag="item]',
data () { // 組件內部的響應式數據
return {
tags:[{name: 1},{name: 2}]
}
},
}
//要渲染的子組件定義
{
name: 'tags-link',
template: 'a[href="javascript:;]@click.stop=navTag:tag@{$tag.name$}',
}
複製代碼
那麼最終渲染的結果就是git
<div>
<a href="javascript:;">1</a>
<a href="javascript:;">2</a>
</div>
複製代碼
實現這個小的組件化框架,主要分爲三個部分:響應式的實現、模板編譯的實現和MVue
類的實現。github
vue2.0
的響應式原理,對響應式數據實現監聽。MVue
類: 主要是負責根據傳入的用戶數據來整合響應式和自定義組件的管理組件化的思路:利用MVue
類的靜態屬性,實現一個全局惟一對象,存儲組件對應的組件工廠實例(本身起的😂)和響應式實例的配置的對組件實現管理。當註冊組件的時候根據對應的配置生成對應的響應式實例配置和組件工廠實例,並保存起來。當組件根實例被掛載時,查找對應的組件,利用組件工廠實例和對應的響應式配置,生成 DOM
片斷,而後掛載到DOM樹
對應的位置。web
總體的架構以下圖所示markdown
這個小框架整體實現的思路和實現的功能大概就是這些,一些細節後續的文章慢慢寫,後面會寫響應式原理的實現和一些組件編譯的東西,不是全部東西都是從vue
源碼來的,有些東西代碼寫的不好勁,見諒。持續學習總結,但願本身一直在前進路上……