最近开始撸vue-next的源码了,慢慢开始理解作者为什么要用Proxy重写一遍了。我们现在在写vue代码的时候会遇到一个很神奇的问题,v-model绑定一个对象中的某一属性时,即便这个属性不存在也可以被绑定,但是若提前声明该属性为null则不能修改他的值,这就是Object.defineproperty的其中一个特征,当属性不存在时能创建一个属性为第一次传递的值,并且保留其数据格式,而且不能挟持到深度的对象属性中,而Proxy则完美的解决了这个问题,不但可以给所有未声明的变量一个默认值,还能对整个对象进行数据监听,而且速度更快,但唯一的劣势是不能在不支持ES6语法的浏览器下使用,所以想兼容目前还是只能使用2.X的vue版本。
具体不同看文章https://blog.csdn.net/qq_37195804/article/details/106094059
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.main{
display: flex;
}
div{
width: 100%;
}
textarea{
width:90%;
height:500px;
}
#jsonWarn,#ymlWarn{
color:red;
}
</style>
</head>
<body>
<div class="main">
<div>
<p>json</p>
<textarea id="json" type="text" oninput="getJson(this)" row="20"></textarea>
<p id="jsonWarn"></p>
</div>
<div>
<p>yml</p>
<textarea id="yml" type="text" oninput="getYml(this)" row="20"></textarea>
<p id="ymlWarn"></p>
</div>
</div>
</body>
<script>
var json = document.querySelector('#json');
var jsonWarn = document.querySelector('#jsonWarn');
var yml = document.querySelector('#yml');
var ymlWarn = document.querySelector('#ymlWarn');
let o = {};
let obj = new Proxy(o,{
get(target,prop) {
return prop in target ? target[prop] : {} //可以给不存在的变量被声明时给一个默认值
},
set(target,prop,value){ //双向绑定
if(prop==='json'){
//输入的json转换成yml
yml.value = changeJson(value);
}else if(prop==='yml'){
//输入的yml转换成json
json.value = changeYml(value);
}
}
})
function getJson(val){
obj.json = val.value
}
function getYml(val){
obj.yml = val.value
}
function changeJson(value){
if(typeof value === 'string'){
try{
var obj = JSON.parse(value)
if(typeof obj ==='object'){
jsonWarn.innerHTML = ''
return jsonToYml(obj).join('\n')
}else{
return ''
}
}catch(e){
jsonWarn.innerHTML = 'json格式错误'
return ''
}
}
}
function changeYml(value){ //jsonToYml格式过两天再撸
return value
}
function jsonToYml(obj,isChild){
var arr = []
if(obj instanceof Array){
obj.forEach(item=>{
if(typeof item==='object'){
arr.push((isChild?' ':'')+'-'+jsonToYml(item,true).join('\n'))
}else{
arr.push((isChild?' ':'')+'-'+item)
}
})
}else {
for(let i in obj){
if(typeof obj[i]==='object'){
arr.push(i+':\n'+jsonToYml(obj[i],true).join('\n'))
}else{
if(isChild){
arr.push(' '+i+':'+obj[i])
}else{
arr.push(i+':'+obj[i])
}
}
}
}
return arr
}
</script>
</html>