vue.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script src="./observer.js"></script>
</head>
<body>
<!-- v-for -->
<!-- arr: (item, index) in arr -->
<!-- obj: (value, key, index) in obj -->
<!-- num: num in number -->
<!-- key number/string 唯一的 -->
<!-- 更改数组 -->
<!-- 1. 不能通过索引的方式去更改数组,这样不会渲染 -->
<!-- 2. 不能通过更该长度的方式去更改数组,这样不会渲染 -->
<!-- 3. 数组变异方法:pop、shift、unshift、splice、sort、reverse、push -->
<!-- 更改对象 -->
<!-- 1. 向对象内添加或者删除属性,不会渲染页面 -->
<!-- 2. vm.$set -->
<!-- Object.defineProperty -->
<div id="app">
<!-- <ul>
<li v-for="(item, index) in arr">{{ item }} --- {{ index }}</li>
</ul> -->
<!-- <h4 v-for="(value, key, index) in obj">{{ value }} --- {{ key }} --- {{ index }}</h4> -->
<!-- <p v-for="item in 10">{{ item }}</p> -->
<!-- <div v-for="item in 'shanshan'">{{ item }}</div> -->
<!-- <ul>
<li
v-for="(fruit, index) in fruitArr"
:key="fruit.id"
>{{ fruit.name }}</li>
</ul>
<button @click="handleClick">click</button> -->
<!-- <li>香蕉</li> 香蕉
<li>苹果</li> 苹果
<li>大鸭梨</li> 大鸭梨
<li>大鸭梨</li> 大鸭梨
<li>苹果</li> 苹果
<li>香蕉</li> 香蕉 -->
<!-- <li>香蕉</li> 0
<li>苹果</li> 1
<li>大鸭梨</li> 2
<li>大鸭梨</li> 0
<li>苹果</li> 1
<li>香蕉</li> 2 -->
<!-- <div v-if="show">
name: <input type="text" key="name">
</div>
<div v-else>
password: <input type="text" key="password">
</div>
<button @click="handleClick">click</button> -->
<!-- <ul>
<li v-for="item in arr">{{ item }}</li>
</ul>
<button @click="handleClick">click</button> -->
<!-- {{ arr }} -->
{{ obj }}
<button @click="handleClick">click</button>
</div>
<!-- <script>
const index = 90;
const fn = (item, index) => {
// console.log(index);
}
fn('a', 80)
const vm = new Vue({
el: '#app',
data: {
show: true,
arr: ['html', 'js', 'vue'],
obj: {
name: 'shanshan',
age: 18,
looks: 'beautiful'
},
fruitArr: [{
name: '香蕉',
id: '001'
}, {
name: '苹果',
id: '002'
}, {
name: '大鸭梨',
id: '003'
}, {
name: '香蕉',
id: '004'
}],
index: 90
},
methods: {
handleClick () {
// this.fruitArr.reverse();
// this.show = !this.show;
// const length = this.arr.length;
// this.arr[length] = 'react';
// this.arr.push('react');
// this.obj.name = 'duyi';
// this.obj.salary = 10000000;
// delete this.obj.name;
this.$set(this.obj, 'salary', 10000000);
}
}
})
setTimeout(() => {
vm.fruitArr.reverse();
}, 2000)
</script> -->
</body>
</html>
observer.js
const data = {
obj: {
a: 1,
b: 10
},
arr: [1, 2, 3]
}
const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);
['shift', 'unshift', 'splice', 'sort', 'push', 'pop', 'reverse'].forEach(method => {
arrayMethods[method] = function () {
arrayProto[method].call(this, ...arguments);
render();
}
})
function defineReactive(data, key, value) {
observer(value);
Object.defineProperty(data, key, {
get() {
return value;
},
set(newVal) {
if (newVal === value) {
return;
}
value = newVal;
render();
}
})
}
function observer(data) {
if (Array.isArray(data)) {
data.__proto__ = arrayMethods;
return;
}
if (typeof data === 'object') {
for (let key in data) {
defineReactive(data, key, data[key]);
}
}
}
function render() {
console.log('渲染');
}
function $set(data, key, value) {
if (Array.isArray(data)) {
data.splice(key, 1, value);
return value;
}
defineReactive(data, key, value);
render();
return value;
}
observer(data);
// const oldPushFn = Array.prototype.push;
// Array.prototype.push = function () {
// oldPushFn.call(this, ...arguments);
// render();
// }
// data.obj = 90;
// data.arr = 80;
// data.obj.a = 10;
// delete data.obj.a;
// data.obj.c = 200;
// data.arr[0] = 10;
// data.arr[10] = 10;
// data.arr.push(1);
// data.arr.reverse();
// console.log(data.arr);
// $set(data.obj, 'a', 100);
$set(data.arr, 0, 1000);
console.log(data.arr);