interface Options {
el: string | HTMLElement
}
interface VueCls {
options: Options
init: () => void
}
interface VNode {
tag: string // div session
text?: string
children?: VNode[]
}
class Dom {
// 创建节点方法
// public允许class、外部、子类使用, 没写都默认public
public createElement(el:string) {
return document.createElement(el)
}
// 填充方法
// private是只允许class内使用,不允许子类和外部使用
private setText(el:HTMLElement, text:string | null){
el.textContent = text
}
// 渲染方法
// protected只允许class内使用和子类使用,通过new的实例无法使用
protected render(data:VNode) {
let root = this.createElement(data.tag)
if (data.children && Array.isArray(data.children)) {
data.children.forEach(element => {
let children = this.render(element)
root.appendChild(children)
})
} else {
this.setText(root, data.text)
}
return root
}
}
// implements 是约束,要求该类一定要有interface的属性和方法
class Vue extends Dom implements VueCls {
// readonly只允许给属性,不允许修改
readonly options: Options
// constructor是接收参数和默认执行方法
constructor(options: Options) {
// 基础父类,需要初始化父类,否则报错,super指代父类,可以通过.获取父类的方法和属性
// 其实就是父类.prototype.constructor.call
super()
// 默认赋值
this.options = options
// 默认执行方法
this.init()
}
// static是不需要通过实例就可以获取的变量或者方法,例如Promise.resolve
static version() {
// static里面的this只能在static里面互通,不能通过this获取class内其他的变量和方法
this.xxx()
return 1.1
}
static xxx() {
}
init():void {
let data:VNode = {
tag: 'div',
children: [
{
tag: 'session',
text: '第一个虚拟node'
},
{
tag: 'session',
text: '第二个虚拟node'
}
]
}
let app = typeof this.options.el === 'string' ? document.querySelector(this.options.el) : this.options.el
// 调用父类方法渲染
app.appendChild(this.render(data))
}
}
new Vue({
el: '#app'
})
// class内的set和get是获取值和设置值的作用,跟defineProperty里面的一样
class Ref {
_value:any
constructor(value) {
this._value = value
}
get() {
return this._value
}
set(newValue) {
this._value = newValue
return this._value
}
}