19. vue的原理

vue:原理1 => Object.defineProperty

當你把一個普通的 JavaScript 對象傳給 Vue 實例的 data 選項,Vue 將遍歷此對象全部的屬性,並使用 Object.defineProperty 把這些屬性所有轉爲 getter/setter。css

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/definePropertyhtml

creat對象

let obj1 = {};
//定義對象 Object.create(null)
//包含 Object類裏的的默認方法 new Object();vue

let obj2 = Object.create(null);
//建立真正的空對象 {裏面生命都沒有}node

exp:react

<script>

let obj1 = {};
//定義對象  Object.create(null)
//包含 Object類裏的的默認方法  new Object();

let obj2 = Object.create(null);     
//建立真正的空對象 {裏面生命都沒有}

console.log(1,obj1);
console.log(2,obj2);

</script>

res:
image
exp:
//定義對象 Object.create(null/obj)git

let p1 = new Person("張三",18);
let p2 = Object.create(p1); ///至關於繼承 本身身上沒有任何屬性github

<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:
imagevuex

語法:

Object.defineProperty(對象, 屬性, 描述對象options)vue-cli

description、options:npm

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:
image

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:
image

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:
image

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:
image

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

選擇安裝的模塊、插件

一、空格 選擇
二、a 全選
三、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

插件的寫法:

一、對象形式
export default {
    install(Vue,options){
            Vue.prototype.$xxx = {
                 methods(){
                        options
                 }
            };
    }
}
二、函數形式
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'),
        }
    }
},

image

相關文章
相關標籤/搜索