19. vue的原理
19. vue的原理
vue:原理1 => Object.defineProperty
当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
creat对象
let obj1 = {};
//定义对象 Object.create(null)
//包含 Object类里的的默认方法 new Object();
let obj2 = Object.create(null);
//创建真正的空对象 {里面生命都没有}
exp:
<script>
let obj1 = {};
//定义对象 Object.create(null)
//包含 Object类里的的默认方法 new Object();
let obj2 = Object.create(null);
//创建真正的空对象 {里面生命都没有}
console.log(1,obj1);
console.log(2,obj2);
</script>
res:
exp:
//定义对象 Object.create(null/obj)
let p1 = new Person("张三",18);
let p2 = Object.create(p1); ///相当于继承 自己身上没有任何属性
<script>
//定义对象 Object.create(null/obj)
class Person{
constructor(name,age){
this.name = name;
this.age = age;
}
getName(){
return this.name;
}
getAge(){
return this.age;
}
}
class Worker extends Person{
}
let p1 = new Person("张三",18);
let p2 = Object.create(p1); ///相当于继承 自己身上没有任何属性
console.log(1,p1);
console.log(2,p2);
console.log(3,new Worker("aaa",10));
console.log("------------------------------------");
console.log(2,p2,p2.name,p2.age,p2.getName,p2.getAge);
</script>
res:
语法:
Object.defineProperty(对象, 属性, 描述对象options)
description、options:
value 初始化值
writable 是否可以修改
enumerable 是否可以枚举(循环、遍历)
configurable 是否可以配置 删除
get 获取数据时触发
set 设置,更改数据时触发
Object.defineProperty(obj,"name",{
value:"abc", 初始化值
writable:true, 是否可以修改
enumerable:true, 是否可以枚举(循环、遍历)
configurable:true, 是否可以配置 删除
});
默认情况下:
value:默认值 undefined
writable/enumerable/configurable都是false
exp1:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
//函数必须有三个参
//Object.defineProperty(对象, 属性, 描述对象options)
//作用 : 用来定义和修改以及监听对象的属性变化的
let obj = {a:1,b:2};
Object.defineProperty(obj,"name",{
value:"abc",
});
//修改
obj.name = "ccc";
//获取
console.log(obj); //{a: 1, b: 2, name: "abc"}
console.log(obj.name);//abc
console.log("------循环 for in --");
for(let name in obj){
console.log(name + ":" + obj[name]);
}//a:1
//b:2
console.log("------循环 Object.keys--");
console.log(Object.keys(obj));//["a", "b"]
console.log(Object.values(obj));//[1, 2]
console.log("------删除 --");
delete obj.name;
console.log(obj.name);//abc
</script>
</head>
<body>
</body>
</html>
res:
exp2:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
//函数必须有三个参
//Object.defineProperty(对象, 属性, 描述对象options)
//作用 : 用来定义和修改以及监听对象的属性变化的
let obj = {a:1,b:2};
Object.defineProperty(obj,"name",{
value:"abc",
writable:true,
enumerable:true,
configurable:true,
});
//修改
obj.name = "ccc";
//获取
console.log(obj);//{a: 1, b: 2, name: "ccc"}
console.log(obj.name);//ccc
console.log("------循环 for in --");
for(let name in obj){
console.log(name + ":" + obj[name]);
}//a:1
//b:2
//name:ccc
console.log("------循环 Object.keys--");
console.log(Object.keys(obj));//["a", "b", "name"]
console.log(Object.values(obj));//[1, 2, "ccc"]
console.log("------删除 --");
delete obj.name;
console.log(obj.name);//undefined
console.log(obj);//{a: 1, b: 2}
</script>
</head>
<body>
</body>
</html>
exp3:
<script>
//函数必须有三个参
//Object.defineProperty(对象, 属性, 描述对象options)
//作用 : 用来定义和修改以及监听对象的属性变化的
let obj = {a:1,b:2};
//get/set ---> value/writable
Object.defineProperty(obj,"name",{
//value:"abc",
get(){
console.log("有人来访问了");
return "abc";
},
set(value){
console.log("有人来修改了"+value);
},
//writable:true,
enumerable:true,
configurable:true,
});
//获取
console.log(1,obj.name, "name" in obj);
//有人来访问了 //1 "abc" true
console.log(2,obj);
//修改 设置
obj.name = 1;//有人来修改了1
console.log("------循环 for in --");
for(let name in obj){
console.log(name + ":" + obj[name]);
}//a:1
//b:2
//有人来访问了
//name:abc
console.log("------循环 Object.keys--");
console.log(Object.keys(obj));
//["a", "b", "name"] //有人来访问了
console.log(Object.values(obj));//[1, 2, "abc"]
console.log("------删除 --");
delete obj.name;
console.log(obj.name,"name" in obj);//undefined false
console.log(obj);
</script>
res:
exp4:
<script>
//函数必须有三个参
//Object.defineProperty(对象, 属性, 描述对象options)
//作用 : 用来定义和修改以及监听对象的属性变化的
let obj = {a:1,b:2};
//get/set ---> value/writable
let initValue = "数据初始化";
Object.defineProperty(obj,"name",{
//value:"abc",
get(){
console.log("get");
return initValue;
},
set(value){
initValue = value;
console.log("set");
},
//writable:true,
enumerable:true,
configurable:true,
});
//获取
console.log("修改前");
console.log(1,obj.name, "name" in obj);//get //1 数据初始化 true
console.log(2,obj); //{a:1,b:2}
//修改 设置
obj.name = 1;//set
console.log("修改后");
console.log(1,obj.name, "name" in obj);//1 true
console.log(2,obj);//{a:1,b:2,name:1}
</script>
res:
exp5:
模仿vue
<script>
//函数必须有三个参
//Object.defineProperty(对象, 属性, 描述对象options)
//作用 : 用来定义和修改以及监听对象的属性变化的
let data = {a:1,b:2};
//Vue:defineReactive
function observer(data){
//[a,b]
Object.keys(data).forEach(function(key){
let initValue = "";
Object.defineProperty(data,key,{
get(){
return initValue;
},
set(value){
initValue = value;
document.body.innerHTML = value;
},
enumerable:true,
configurable:true,
});
})
}
observer(data);
document.onclick = function(){
//document.body.innerHTML = 12;
data.a = 12;
console.log(data)
}
</script>
vue:原理2 => vue3 代理 ==proxy==
一切操作都走代理对象!
let proxy = new Proxy(需要代理的对obj,代理处理的功能{
get(target,key,proxy){}
set(target,key,value,proxy){}
has(target,key){}
deleteProperty(target,key){}
});
exp1:
<script>
//proxy - 监听 Object.observe()
let data = {
a:1,
b:2
}
let proxy = new Proxy(data,{
get(){
console.log("有人来get");
},
set(){
console.log("有人来set");
}
});
proxy.a;//有人来get
proxy.a = 12;//有人来set
</script>
exp2:
<script>
//proxy - 监听 Object.observe()
let data = {
a:1,
b:2
}
let proxy = new Proxy(data,{
get(target,key,proxy){
//console.log("get",target == data,key,proxy);
///console.log("get this",this);
return target[key];
},
set(target,key,value,proxy){
console.log("set",target,key,value,proxy);
target[key] = value;
}
});
//设置
proxy.a = 12;
//获取
console.log("获取:",proxy.a);
</script><script>
//proxy - 监听 Object.observe()
let data = {
a:1,
b:2
}
let proxy = new Proxy(data,{
get(target,key,proxy){
//console.log("get",target == data,key,proxy);
///console.log("get this",this);
return target[key];
},
set(target,key,value,proxy){
console.log("set",target,key,value,proxy);
target[key] = value;
}
});
//设置
proxy.a = 12;//set {a: 1, b: 2}, a ,12 , proxy{a: 1, b: 2}
//获取
console.log("获取:",proxy.a);//获取:12
</script>
exp3:
<script>
//proxy - 监听 Object.observe()
let data = {
a:1,
b:2
}
let proxy = new Proxy(data,{
get(target,key,proxy){
//console.log("get",target == data,key,proxy);
///console.log("get this",this);
return target[key];
},
set(target,key,value,proxy){
console.log("set",target,key,value,proxy);
target[key] = value;
}
});
//设置
proxy.a = 12;//set {a: 1, b: 2}, a ,12 , proxy{a: 1, b: 2}
//获取
console.log("获取:",proxy.a);//获取:12
</script>
模拟报错:
<script>
//proxy - 监听 Object.observe()
let data = {
a:1,
b:2
}
let proxy = new Proxy(data,{
get(target,key,proxy){
return target[key];
},
set(target,key,value,proxy){
target[key] = value;
//document.body.innerHTML = value;
},
has(target, key){
console.log("has");
//return key in target;
if(key in target){
return true;
} else {
throw new Error(`1111[Vue warn]: Property or method "${key}" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
(found in <Root>)`)
}
},
deleteProperty(target, key){
console.log("del");
if(key in target){
return delete target[key];
} else {
return false;
}
}
});
console.log(1111,"c" in proxy);
//console.log(delete proxy.c);
document.onclick = function(){
//document.body.innerHTML = 12;
proxy.a = 12;
}
</script>
</head>
<body>
<div id="app">
{{a}}--{{b}}-{{c}}
</div>
</body>
<script>
let vm = new Vue({
el:"#app",
data,
});
</script>
res:
vue-cli:2.x
https://www.npmjs.com/package/vue-cli
vue-cli:3.x
https://cli.vuejs.org/ 英文
https://cli.vuejs.org/zh/ 中文
https://github.com/vuejs/vue-cli
注意:vue-cli2升级到vue-cli3必须先删除原来的模块
cnpm i -g vue-cli
cnpm i -g @vue/cli 必须先删除vue-cli
https://www.jb51.net/article/137710.htm
创建项目命令
2.x vue init
3.x vue create
exp:
vue create myvue3
选择安装的模块、插件
1、空格 选择
2、a 全选
3、i 反选
这里是把babel,postcss,eslint这些配置文件放哪
独立文件放置 √
放package.json里
启动项目命令
2.x npm start
3.x npm run serve
配置代理服务器/端口
需要创建 vue.config.js 文件盒工程文件(package.json)是平级
devServer: {
port:9000,
// proxyTable: {
proxy: {
"/anhao": {
target: "http://localhost:3000",
changeOrigin: true,
pathRewrite: { //需要rewrite重写的, 如果在服务器端做了处理则可以不要这段
"^/anhao": ""
}
},
},
}
}
vue add router cnpm i -S router
vue add vuex vue i -S vuex
-------------------------------------------------
插件: https://github.com/RuMengkai/awesome-vue
element
mint-ui
插件的写法:
1、对象形式
export default {
install(Vue,options){
Vue.prototype.$xxx = {
methods(){
options
}
};
}
}
2、函数形式
export default (Vue,options)=>{
Vue.prototype.$xxx = {
methods(){
options
}
};
}
使用:
Vue.use(插件模块);
vue-cli:用的vue.js
myvue\node_modules\vue\dist\package.json
"main": "dist/vue.runtime.common.js",
不要采用runtime形式的文件
最好采用 dist/vue.esm.js
添加 配置文件:vue.config.js 在项目的根目录下
configureWebpack: config => {
config.resolve = {
extensions: ['.js', '.vue', '.json',".css"],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
}
},