vue相关内容以及深拷贝和浅拷贝
Vue相关内容
概述:
vue是前端的一个js库(诞生于2015年 兴起于2016年) ,vue是一个MVVM模式
M model数据
V view 视图
VM viewModel 视图模型 数据驱动视图 数据变了视图就会变(自动调用)
Vue的双向数据绑定
双向数据绑定的概述
- 视图变化–数据也会变化
- 数据变化–视图也会变化
双向数据绑定运用表单标签的
代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="msg">
</div>
<script>
new Vue({
el: '#app', //挂载的地方
data: {
msg: '你好' //放数据的
}
})
</script>
</body>
</html>
利用原生js实现Vue2的双向数据绑定
class Vue {
constructor(option) {
this.el = document.querySelector(option.el) //找到对应渲染的元素
//渲染元素里面的数据
this.data = option.data
//使用Object.defineProperty的使用
//浅拷贝
this.model = Object.assign({}, option.data)
//拿到传入的元素里面的内容 是在div里面显示的内容
this.template = document.querySelector(option.el).innerHTML
}
_obServer() {
//防止this指向改变
let _this = this
//看数据里面有什么元素
for (let key in this.data) {
Object.defineProperty(this.data, key, {
get() {
return _this.model[key]
},
set(v) {
_this.model[key] = v
}
})
}
}
// 数据渲染
render() {
let _this = this
//让页面上的内容显示为去掉花括号之后的内容 str={{msg}}
this.el.innerHTML = this.template.replace(/\{\{\w+\}\}/g, (str) => {
let propertyName = str.substring(2, str.length - 2).trim() //msg
console.log(str);
return _this.data[propertyName] //返回值就是页面显示的内容
})
//找到对应的el里面的input框 过滤掉没有v-model属性的输入框
Array.from(this.el.querySelectorAll('input')).filter((input) => {
//返回具有v-model属性的input框
return input.getAttribute('v-model')
}).forEach((input) => {
let _this = this
//找到输入框中对应的是哪个元素
let propertyName = input.getAttribute('v-model').trim()
input.onchange = function() {
_this.data[propertyName] = this.value //将data里面的数据改为输入框的数据
}
//将input的数据改为data里面的数据
input.value = this.data[propertyName]
})
}
}
深拷贝和浅拷贝
浅拷贝
简单来说就是创建一个新对象,这个对象拥有被拷贝对象属性值的拷贝.如果被拷贝对象的属性是基本数据类型,那么拷贝的就是基本数据类型的值,如果属性是引用数据类型,拷贝的就是内存地址(如果某一个对象的引用数据类型的值改变另外一个也会改变)
相当于复制一个快捷方式 两个快捷方式操作都会改变文件的内容
Object.assign实现浅拷贝
//浅拷贝会开辟一个新的内存空间,如果<属性>是基本类型就是直接赋值,如果<属性>是引用类型就会说内存地址
let obj = {
name: 'jack',
list:[123]
}
let newObj = Object.assign({}, obj) //返回的是一个新的对象
console.log(obj ==newObj);//false
console.log(newObj.list==obj.list);//true
Array.prototype.concat(数组的浅拷贝)
//数组的浅拷贝
let arr = [{
name: 'jack',
pwd: '123'
}, {
name: 'tom',
pwd: '123'
}]
let newArr = [].concat(arr)
console.log(newArr == arr); //false
console.log(newArr[0]);
console.log(newArr[0] == arr[0]); //true
Array.prototype.slice(数组的浅拷贝)
let copyArr = arr.slice()
console.log(copyArr == arr); //false
console.log(copyArr[0] == arr[0]); //true
…扩展运算符
let copyArr2 = [...arr]
console.log(copyArr2 == arr); //false
console.log(copyArr2[0] == arr[0]); //true
自定义函数实现浅拷贝
function copy(obj) {
let constructor = obj.constructor //指向他的构造函数
let copyObj = new constructor() //创建一个新对象
for (let key in obj) {
copyObj[key] = obj[key] //将原来的值一一赋给新对象
}
return copyObj
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ShBcnjR5-1667644397366)(C:\Users\ThankPad\AppData\Roaming\Typora\typora-user-images\1667642844043.png)]
深拷贝
意思是将一个对象完整的从内存中拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,跟原来的对象互不干扰(相当于拷贝一份完整的文件,我操作新的文件对原来的文件没有影响)
序列化和反序列化(JSON.Stringify JSON.parse)
let obj = {
list: [{
name: '苹果'
}, {
name: '香蕉'
}]
}
let copyobj = JSON.parse(JSON.stringify(obj))
console.log(copyobj == obj); //false
console.log(copyobj.list == obj.list); //false
console.log(copyobj.list[0] == obj.list[0]); //false
自定义函数实现深拷贝
function deepClone(obj) {
//判断传入的参数是否是一个对象并且不是null 如果都不是就直接返回
if (!(typeof obj == 'object' && obj)) {
return obj
}
//是对象就给一个空对象 是数组就给一个空数组
let copyObj = obj instanceof Array ? [] : {}
for (let key in obj) {
//递归函数 当不知道循环有多少层的时候就需要用到递归函数
copyObj[key] = (obj[key]) //当前的这个属性在调用这个函数,其他的都没变
}
return copyObj
}
console.log(deepClone(obj));