前言
大家好 今天继续给大家带来手写vue2中的解析模板参数
目录结构
依赖文件
{
"name": "geyaohandvue2",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "rollup -cw"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.23.3",
"@babel/preset-env": "^7.23.3",
"rollup": "^2.79.1",
"rollup-plugin-babel": "^4.4.0"
},
"dependencies": {
"@rollup/plugin-node-resolve": "^15.2.3"
}
}
complier–index.js
export function completeToFunction(template){
console.log(template,"template is")
}
observe—array.js
let oldArrayProto=Array.prototype;
export let newArrayProto=Object.create(oldArrayProto)
let methods=['push','pop','shift','unshift','reserve','sort','splice']
methods.forEach(method=>{
newArrayProto[method]=function(...args){
const result=oldArrayProto[method].call(this,...args)
let inserted;
let ob=this.__ob__;
switch(method){
case 'push':
case 'unshift':
inserted=args;
break
case 'splice':
inserted=args.splice(2);
break
default:
break
}
console.log(inserted)
if(inserted){
ob.observeArray(inserted)
}
return result
}
})
observe----index.js
import { newArrayProto } from "./array"
class Observer{
constructor(data){
Object.defineProperty(data,'__ob__',{
value:this,
enumerable:false
})
// data.__ob__=this
if(Array.isArray(data)){
data.__proto__=newArrayProto
this.observeArray(data)
}else{
this.walk(data)
}
}
walk(data){
Object.keys(data).forEach(key=>defineReacttive(data,key,data[key]))
}
observeArray(data){
data.forEach(item=>observe(item))
}
}
export function defineReacttive(target,key,value){
observe(value)
Object.defineProperty(target,key,{
get(){
console.log("用户取值了")
return value
},
set(newValue){
console.log("用户设置值了")
if(newValue===value) return
value=newValue
}
})
}
export function observe(data){
if(typeof data!=='object'||data==null){
return;
}
if(data.__ob__ instanceof Observer){
return data.__ob__
}
return new Observer(data)
// 判断一个对象是否被劫持
}
index.js
import { initMixin } from "./init"
function Vue(options){
this._init(options)
}
initMixin(Vue)
export default Vue
init.js
import { initState } from "./state"
import { completeToFunction } from "./complier/index"
export function initMixin(Vue){
Vue.prototype._init=function(options){
// $options 获取用户的配置
const vm=this
vm.$options=options
initState(vm)
}
Vue.prototype.$mount=function(el){
const vm=this;
el=document.querySelector(el)
let ops=this.$options
if(!ops.render){
let template;
if(!ops.template&&el){
template=el.outerHTML
}else{
if(el){
template=ops.template
}
}
if(template){
const render=completeToFunction(template)
ops.render=render
}
console.log(template)
}
ops.render
}
}
state.js
import { observe } from "./observe/index"
export function initState(vm) {
const opts = vm.$options
if (opts.data) {
initData(vm)
}
}
function proxy(vm,target,key){
Object.defineProperty(vm,key,{
get(){
return vm[target][key]
},
set(newValue){
vm[target][key]=newValue
}
})
}
function initData(vm) {
let data = vm.$options.data
data=typeof data === 'function' ? data.call(vm) : data
console.log(data)
vm._data = data
observe(data)
for(let key in data){
proxy(vm,'_data',key)
}
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<div>{name}</div>
<div>{age}</div>
</div>
<script src="./vue"></script>
<script>
const vm=new Vue({
data(){
return {
name:'geyao',
age:20,
hobby:["geyao","fangfang","nice"]
}
},
template:'<div>hello</div>'
})
vm.$mount("#app")
</script>
</body>
</html>