模拟一个其他人写的代码, 框架的源码 把需要渲染的代码, 都放到HTML 中, 然后由我这段代码帮助我们去渲染
<div id="app">
<h1>{{name}}</h1>
<h1>{{age}}</h1>
<h1>{{sex}}</h1>
<h1>{{height}}</h1>
</div>
<script>
// 模拟一个其他人写的代码, 框架的源码 把需要渲染的代码, 都放到HTML 中, 然后由我这段代码帮助我们去渲染
function observer(options) {
/**
* options 是 函数 observer de 形参 传递进来的实参是 调用函数 observer 是 给的实参 * {foot:'#app',
* data:{
* name:'张三',
* age:18,
* sex:'男'}
*
*/
//1验证 root 有没有传递
if (options.foot === undefined) {
//手动配置报错
throw new Error('您没有传递 root 属性,请从新传递')
}
//2验证root节点有没有获取到
const rootHtml = document.querySelector(options.foot)
// console.log(footHtml)
if (rootHtml === null) {
//手动配置报错
throw new Error('您传递的foot 的属性有问题请从新传递')
}
//3验证 data 没有有传递
if (options.data === undefined) {
//手动配置报错
throw new Error('您没有传递 data 请从新传递')
}
//4验证传递的data是不是一个 对象
if (options.data.constructor !== Object) {
//手动配置报错
throw new Error('您传递的data 不是一个对象 请重新配置')
}
//4.1 备份一份最处的 html 文本
const rootHtmlStr = rootHtml.innerHTML
//5将劫持的数据完整的劫持一份到 对象 _data 中
const _data = {}
//5.1循环遍历 对象 observer 里 的 对象 data 拿到每一个 k
for (let k in options.data) {
// 5.2 劫持的数据完整的劫持一份到 对象 _data 中
Object.defineProperty(_data, k, {
get() {
//函数执行 返回 这个对象里所有的 k
return options.data[k]
},
set(val) {
//做出修改时 将修改的值赋值给 这个对像 对应的 k
options.data[k] = val
rander(rootHtml, _data, rootHtmlStr )
}
})
}
//5.3 首次执行 渲染页面 通过回调函数 来渲染
rander(rootHtml, _data, rootHtmlStr )
//5.4 返回一个 劫持后的数据
return _data
}
//准备函数 用来回调
function rander(rootHtml, _data, str) {
//准备正则 要符合 当前节点中 的 打印出来的 字符形式 ---> console.log(rootHtmlStr)
// console.log(rootHtml)
// console.log(_data)
// console.log(str)
const reg = /{{ *(\w+) *}}/g
//匹配节点中所有的花括号, 存放在一个数组中 返回值是一个包含所有 符合 正则的 要求 的字符串组成的数组
const res = str.match(reg)
console.log(res)
//遍历数组,拿到每一个 花括号
res.forEach((item) => {
//拿到花括号里的 文本 因为这是 对象 中的 key
const key = reg.exec(str)[1]
console.log(key)
// 将原本花括号内部的文本, 全部替换为 截取到数据的那个对象里 的实际的值
str = str.replace(/{{ *(\w+) *}}/, _data[key])
console.log(str)
console.log(_data[key])
})
//最后将修改完成的字符串 渲染到页面
rootHtml.innerHTML = str
}
const app = observer({
foot: '#app',
data: {
name: '张三',
age: 18,
sex: '男',
height:180
}
})
console.log(app)
</script>