这个一样是写博客的产出,以前在写博客的时候,瞎弄了一个模板引擎,当时就想以后把他优化一下,把 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
源码来的,有些东西代码写的不好劲,见谅。持续学习总结,但愿本身一直在前进路上……