學習Vue響應式原理,實現一個小「框架」(1):思路分析

前言

這個一樣是寫博客的產出,以前在寫博客的時候,瞎弄了一個模板引擎,當時就想以後把他優化一下,把 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

  1. 單個元素的屬性和文本的定義div[class="box]{hahaha} 表示 <div class="box">hahaha</div>
    • [] 屬性 =》 寫法:[class="box,id="box]
    • {} 文本 =》 寫法: {hahaha}
  2. 數據綁定與過濾器h6[class="font-$regular$]{ 建立時間:$article.createtime$ -- 修改時間:$article.modifiedtime:time$}
    • $data$ 兩個$之間寫上組件實例定義的變量名或者父組件傳入的變量
    • :以後的爲組件實例定義的方法,會將函數返回結果填充載$之間
  3. 事件的綁定a@click.stop=nav:article@[href="javascript:;,class="title]
    • 兩個@之間爲組件綁定的事件部分事件名.stop=方法名:參數1:參數2
    • 只有阻止冒泡的功能,傳入的參數能夠有多個也能夠不傳,能夠是變量名,也能夠是字符串
  4. innerHtml的使用div[class="markdown-body,style="padding: 0;]^article.abstract:markdown^
    • 兩個^之間是對應的html綁定部分(會忽略{})=》變量名:方法名
    • 內部的效果就是div.innerHtml = 返回值
  5. 模板中自定義組件的使用article-item[:article="item]
    • 組件只要在渲染以前註冊就能夠在模板中使用
    • [:article="item]表示 :組件的屬性名="當前組件的變量名,屬性名綁定後能夠在組件中直接使用該變量名(沒有聲明),屬性能夠層層傳
  6. 元素層級關係div>(a+article-item)
    • > 父子關係
    • + 兄弟關係
    • () 優先運算同一層級
  7. 列表渲染的使用
    • 因爲列表渲染比較難搞我就簡單實現了一下,有許多限制
    • 只能針對自定義組件列表渲染
    • 不能在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的響應式原理,對響應式數據實現監聽。
  • 模板編譯:主要是實現如何根據模板語法生成DOM元素和添加響應式依賴。
  • MVue類: 主要是負責根據傳入的用戶數據來整合響應式和自定義組件的管理

組件化的思路:利用MVue類的靜態屬性,實現一個全局惟一對象,存儲組件對應的組件工廠實例(本身起的😂)和響應式實例的配置的對組件實現管理。當註冊組件的時候根據對應的配置生成對應的響應式實例配置和組件工廠實例,並保存起來。當組件根實例被掛載時,查找對應的組件,利用組件工廠實例和對應的響應式配置,生成 DOM片斷,而後掛載到DOM樹對應的位置。web

總體的架構以下圖所示markdown

20200720-192742-0296.jpg

總結

這個小框架整體實現的思路和實現的功能大概就是這些,一些細節後續的文章慢慢寫,後面會寫響應式原理的實現和一些組件編譯的東西,不是全部東西都是從vue源碼來的,有些東西代碼寫的不好勁,見諒。持續學習總結,但願本身一直在前進路上……

項目源碼:傳送門 實現效果:個人博客就是用這個小框架改造的

相關文章
相關標籤/搜索