当前位置: 首页 > news >正文

Vue框架基础知识

1.基础知识

1.获取原型

第一种方式:使用构造函数的属性prototype(显示原型(实例原型))

第二种该方式:使用实例的隐藏属性__proto__(即实例对象上有一个隐藏属性__proto__)(隐式原型)

第三种方式:使用Object.getPrototypeOf()方法

2.原型的作用:为了实现属性和方法的共享。

在原型上定义的属性和方法可以被由该构造函数创建出来的所有对象实例共享。

案例:

function Person(name,age){

    this.name = name;

    this.age = age;

    this.sayHi =function(){

        console.log(this.name,this.age);

    }

}

//定义俩个对象

let p1 = new Person("张三",21);

let p2 = new Person("李四",19);

//想要在p1对象上添加gender属性。

p1.gender="女";

p2.gender="男";

console.log(p1);

console.log(p2);

console.dir(Person);//构造函数不会新增属性


 

//在原型上,定义一个属性address,

Person.prototype.address="我家的地址"

//验证:实例对象上是否又该属性

console.log(p1.address);//我家的地址

console.log(p2.address);//我家的地址

//验证:实例对象是否可以修改原型上"继承"过来的属性,//如果修改的是原型上的属性值,那么p2也应该变

p1.address="北京海定区";//实际上address是实例对象自己的属性

console.log(p2.address);//我家的地址     没有改变原型上的属性值。

//注意:在原型上添加属性,只是给实例上的属性进行初始化

console.dir(Person);//构造函数不会新增属性

//在原型上,定义一个公有的方法:showInfo()

Person.prototype.showInfo = function (){

    console.log(this.name,this.age);

   

}

p1.showInfo()

p2.showInfo()

 总结:

1.在原型上绑定一个属性,所有的实例对象都可以`继承`这个属性

2.实例对象修改了原型上继承过来的属性,实际上是实例对象新添加了一个与原型属性同名的属性而已。实例对象并不会覆盖原型上的属性值

3.在原型上绑定一个属性,构造函数中不会新增属性。

4.还可以绑定公有的方法。

3.原型链

1.原型链:当访问一个对象的属性或方法时,首先JavaScript引擎会从对象自身上去找,如果找不到,就会往原型中去找 ,再找不到就会到原型的原型中去找,因为构造函数是对象,实例原型也是对象,他们都有__proto__隐藏属性,这样就形成了链式的结构,这个链式结构就是原型链。

在 JavaScript 中,Object.prototype 本身也是一个对象,它也有自己的原型。Object.prototype 的原型实际上是 null。这是因为在 JavaScript 的原型继承链中,Object.prototype 是顶层原型对象,它没有更高的原型对象。 

2.模块化编程

1.没有模块化编程时的影响:

1.都是通过<script src="">标签来引入到同一个html文件中。 当我们引入多个js文件,不同的js文件可能会有相同的变量名字,那么后引入的就会覆盖先引入的。即所有的js文件都是再全局空间进行定义的,每个js文件没有自己私有的命名空间。

2.多个js文件如果存在依赖关系,必须确保引入顺序的正确性,才不会报错,如果js文件之间的依赖关系很复杂,那么这样的引入顺序就非常难以维护。

2.模块化编程

 1.模块化编程:是指将复杂的代码拆分为多个独立的模块,每个模块负责完成特定的功能。某一个模块,可以通过使用export关键字将代码导出成为模块;一个模块也可以通过使用import关键字导入其他模块到该模块。

优点:

1.防止命名冲突,每个模块都有自己的命名空间

2.代码复用,每个模块可以被其他多个模块引用

3.高维护性,修改一个模块其他引用该模块的地方都改变

4.使用模块化之后一般都是在自己的模块中引入所依赖的模块 ,避免了依赖顺序的引入问题

3.常用的模块化范式

CommonJS: 主要用在Node.js环境下

AMD:是一种用于浏览器环境的异步模块加载规范,主要用于解决浏览器中多个脚本文件的依赖问题。

ESM(ECMAScript Modules): 是 JavaScript 的内置模块系统,它已经成为 Web 和 Node.js 的标准。

TypeScript:TypeScript 是 JavaScript 的超集,它提供了静态类型检查和其他高级特性,非常适合模块化开发。

4.ESM范式的语法

模块功能主要由两个命令构成:export和import

1.export命令:导出(暴露)模块。可以让其他模块来发现和引入该模块,有三种方式

    (1)分别暴露:就是在要暴露的变量前加上export关键字

export1.js

export let name = "zhangsan"

export let person= {name:"李四",age:21}

export function isPrime(num){

    console.log("使用了分别方式暴露的方式:");

    let f = true;

    for (let i = 2; i < num-1; i++) {

        if(num%i==0){

            f=false;

        }

    }

    if(f){

        console.log(num,"是素数");

       

    }else{

        console.log(num,"不是素数");  

    }

}

 (2)统一暴露::export{....要暴露的名字.....}

export2.js

let username = "zhangsan"

let obj= {name:"李老四",age:21}

function isPrime(num){

    console.log("执行统一暴露的方法");

   

    let f = true;

    for (let i = 2; i < num-1; i++) {

        if(num%i==0){

            f=false;

        }

    }

    if(f){

        console.log(num,"是素数");

       

    }else{

        console.log(num,"不是素数");  

    }

}

//暴露方法2:统一暴露:export{....要暴露的名字.....}

export{username,obj,isPrime}

 (3)默认暴露,只能暴露一个内容,使关键字default

let student = {

    name:"小明",

    age:17,

    sayhi(){

        console.log(this.name,this.age);    

    }

}

//默认暴露的的第一种写法:

export default student;

//默认暴露的的第二种写法:

export default{

    name:"小明",

    age:17,

    sayhi(){

        console.log(this.name,this.age);    

    }

}

2.import引入模块

在script标签中导入模块,注意不要忘记在标签种加上属性/type="module",否则浏览器不认为是模块导入,不识别import语法

(1)第一种方式:通用导入方式   from后的相对路径不能省略 ,该方式可以应对所有的暴露方式

格式:import * as 别名 from "js文件地址" 

访问变量时,直接使用  别名.变量名

访问对象的属性或方法时,别名.对象名.属性名或者方法名

访问函数时,使用   别名.函数名

注意:使用默认方式暴露模块里的内容时,需要使用关键字default关键字,并且别名就是对象名

访问对象的属性时:使用别名.default.属性名或者方法名

//第一种方式: 通过导入方式 from后的相对路径不能省略

        // import * as m1 from "./export1.js";

        // import * as m2 from "./export2.js"

        // import * as m3 from "./export3.js"

        // console.log(m1.name,m1.person.name,m1.person.age);

        // m1.isPrime(17)

        // console.log(m2.obj);

        // m2.isPrime(19)

       

        //使用默认方式暴露模块理的内容时:需要使用关键字default关键字

        //注意:导入默认暴露方式时,别名就是对象名

        // console.log(m3.default.name);

        // m3.default.sayhi();

 (2)解构赋值方式:适用于分别暴露、统一暴露的语法

格式:import {变量名1,变量名2,......} from "js文件地址"

注意:变量名必须和js文件中的变量名一致。如果导入的一些模块中有重名的函数名,那么可以给函数名起别名

格式:import {变量名1 as 别名1,变量名2 as 别名2,......} from "js文件地址"

2.默认暴露语法

import {default as 别名} from "js文件地址"

// //使用第二种方式:解构赋值方式

        // import  {isPrime,name,person} from "./export1.js"

        // isPrime(26)

        // console.log(name,person.name);

       

        // console.log("-------------------------");

        // //解构赋值方式,可以给单独某一个变量起别名.避免和之前导入的模块变量名冲突

        // import{username,obj,isPrime as isPrime1} from "./export2.js"

        // isPrime1(7)

        // console.log("-------------------------");

        // //解构赋值方式导入默认暴露的模块,使用别名时,不需要添加default关键字.

        // import {default as m3} from "./export3.js"

        // console.log(m3); //李四  (暴露变量)

        // m3.sayhi()

(3)简单方式:只适合默认暴露方式

格式:import 变量名 from "js文件地址"

// import m3 from './export3.js'

        // console.log(m3);

        // m3.sayhi()

 3.入口文件:把所有的模块引入放到一个JS文件(比如main.js)中,叫做入口文件,然后html里再引入入口文件,别忘记type='module'.

格式:<script type="module" src="入口文件"></script>

注意: 入口文件的用途,是在HTML中引用,让HTML可以识别到所有的js模块。 并不是让我们在html里的script中书写模块里的函数,或者变量等

3.代理模式

1.数据代理(数据劫持):指的是在访问或者修改对象的某个属性时,通过一段代码拦截这个行为,进行额外的操作或者修改返回结果。

数据劫持最著名的应用当属双向绑定 

双向绑定的核心思想是在视图层和数据层之间建立一种自动同步的机制,使得数据的变化能够自动反映到视图上,反之亦然。

Vue.js 采用了一种基于 Object.defineProperty 的数据劫持方式来实现双向绑定

2.Object.defineProperty():该方法可以在对象上新添加属性,或者修改已经存在的属性

默认情况下,使用 Object.defineProperty() 添加的属性是不可写、不可枚举(遍历)和不可配置(删除或修改)的。但是我们可以通过参数来改变这些。

/三个参数:第一个参数表示要代理的对象,第二个参数表示要新增或者修改的属性名

//第三个参数是属性描述符,对象写法

Object.defineProperty(目标对象,新增属性,{

    value:(新增属性的初始值),

    writable:true,//用来描述是否可以被修改,默认是fasle,不可以修改,true,表示可以修改

    enumerable:true,  //用来描述属性是否可以被枚举,默认值是false,表示不能被枚举

    //true,表示可以枚举

    configurable:true  //用来描述属性是否可以被删除或者

    //是否可以再次通过属性描述符的方式修改,默认值是false,表示不能删除或修改

    //true  表示可以删除或修改

})

添加对象属性:

测试:writable,enumerable,configurable四个属性主要对新增的属性起作用。 

Object.defineProperty(person,"idcardNo",{

    value:1001,

    writable:true,//用来描述是否可以被修改,默认是fasle,不可以修改,true,表示可以修改

    enumerable:true,  //用来描述属性是否可以被枚举,默认值是false,表示不能被枚举

    //true,表示可以枚举

    configurable:true  //用来描述属性是否可以被删除或者

    //是否可以再次通过属性描述符的方式修改,默认值是false,表示不能删除或修改

    //true  表示可以删除或修改

})

console.log("-----------------");

console.log(person);

//验证:代理方法添加的新属性是否可以被枚举

console.log(Object.keys(person));

Object.defineProperty(person,"idcardNo",{

    value:30

})

console.log(person);

 delete person.idcardNo;

console.log(person);

4.响应式页面设计

什么是响应式:它允许我们的应用程序在用户与界面交互时,动态地更新视图。这种交互性使得我们的应用程序能够实时地响应用户的操作。

响应式原理的核心思想是:当数据发生变化时,能够自动地更新视图。为了实现这一目标,我们需要对数据的变化进行监听,并在数据发生变化时触发视图的更新。

let person ={name:"michael",age:21}

let divDom =  document.getElementById("container");

//既然使用了代理对象,那么就不应该直接操作目标对象,所以需要定义一个代理对象

let myname =""

let pr =  Object.defineProperty(person,"name",{

        //set方法:一旦监听的属性的值被修改了,该方法就会被调用,形参是修改的值

        set(value){

            console.log("------set方法被调用了-------"+value);

            divDom.innerText = value;

            myname=value;

        },

        get(){

        //    return person.name  

          //不能直接访问目标对象或者代理对象的属性,否则出现栈溢出,死循环

          //需要借助外部的一个临时变量

          console.log("--------get方法被调用了-------------");

          return myname;

        }

    })

pr.name="李四" //直接使用代理对象来修改属性的值  // 修改值就调用set方法

console.log(person.name);  //获取值就带用get方法

pr.name = "王老六";  

//使用了数据代理后对象和代理对象的输出是一摸一样的

console.log(person);

console.log(pr);

 5.数据代理(双向绑定)

//自定义一个类型,代理对象

class ProxyObject{

    //构造器传入一个形参,表示要代理的目标对象

    constructor(obj){

        //将this的属性_data指向obj指向的对象

        this._data = obj;

        //遍历目标对象上的所有属性

        for (let prop in obj){

            //数据劫持每一个属性

            if(obj.hasOwnProperty(prop)){

                //因为要做代理,因此应该给代理对象添加目标对象的属性,用的时候应该使用代理对象的该属性进行访问和修改

                Object.defineProperty(this,prop,{   //this是指代理对象, Object.defineProperty给代理对象添加目标对象的属性

                    //get方法

                    get(){

                        console.log("get方法");

                       

                        //如果有人想要获取目标对象上的属性值,就给它代理对象的该属性值

                        return this._data[prop]

                    },

                    set(value){

                        console.log("set方法");

                        ///如果修改了代理对象上的劫持的那个属性值,我们就修改代理对象的另一个属性_data.

                        //_data和目标对象指向同一个对象

                        this._data[prop]=value;

                    }

                })

            }

        }

    }

}

 写一个完整的对象代理:根据上面自定义的类

let person = {

    name:"zhangsan",

    age:21,

    gender:'女',

    // hobbies:{h1:"book",h2:"movie",h3:"music"}

}

//代理对象

let proxy = new ProxyObject(person) (上面定义的类)

//修改目标对象上的某一个属性,然后查看代理对象上的属性值是否也改变了

person.name="王老六";

console.log(proxy.name);

console.log(person.name);

//修改代理对象上的某一个属性,然后查看目标对象上的属性值是否也改变了

// proxy.age=30;

// console.log(proxy.age);

// console.log(person.age);

 6.做数据代理的缺点

1.不能监听数组的变化,数组的以下几个方法不会触发 set方法:

比如:push    pop    shift    unshift    splice    sort    reverse

2.必须遍历对象的每个属性

3.必须深层遍历嵌套的对象

7.Proxy

1.Proxy是ES6引入的一个新对象,用于创建一个对象的代理,可以拦截并重定义基本的操作。

可以被认为是 Object.defineProperty() 的升级版。

外界对某个对象的访问,都必须经过这层拦截。因此它是针对 整个对象,而不是 对象的某个属性,所以也就不需要对 keys 进行遍历。

语法:const p = new Proxy(target, handler)

  • target :目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。

  • handler :以函数作为属性的对象,实现拦截和自定义操作。(handler是一系列的被自动触发函数。常用的有set/get捕获器)

案例:

let person = {

    name:"张三",

    age:21,

    gender:'女'

}

const p1 = new Proxy(person,{

    //属性被访问的时候,会自动触发

    get(target,property){

        console.log("get");

        return target[property];

    },

    //当属性被改变时,会自动触发

    set(target,property,value){

        console.log("----set方法----"+value);

        target[property] = value;

        return true;

    },

    //当删除属性时,会自动触发

    deleteProperty(target,property){

        console.log("--------deleteProperty---------");

        delete target[property]

        return true;

    },

    //当查看是否有该属性时会自动触发

    has(target,property){

        console.log("--------has---------"+property);

        return property in  target

    },

    defineProperty(target,property){

        console.log("--------defineProperty--------属性:-"+property);

        return Object.defineProperty(target,property,{})

    }

})

console.log(p1.name);

console.log("-------------");

p1.name="张老师"

console.log("-------------");

console.log(p1.name);

p1.age=40

console.log("-------------");

console.log(p1.age);

console.log("-------------");

console.log(person.age);

console.log("-------------");

delete p1.name

console.log("*************");

//has方法,使用in时才会触发。for...in不会触发

console.log("age" in p1);

console.log("*************");

let p2 = Object.defineProperty(p1,"age",{})

p2.age=40

console.log(person.age);

console.log("*************");

console.log(p2.age);

8.响应式页面

html代码:

<body>

    <div id="container"></div>

</body> 

let person = {name:"zhangsan",age:21}

document.getElementById("container").innerText=person.name

//使用代理方式,来做一个页面的响应式处理

const p1 = new Proxy(person,{

    set(target,property,value){

        document.getElementById("container").innerText=value

        return true;

    }

});

p1.name="李四";  //数据改变,视图上(页面)会自动更新

p1.name="李四1";


http://www.mrgr.cn/news/54719.html

相关文章:

  • 关于Qt中进行输出的方式及对比分析
  • OpenAI GPT-o1实现方案记录与梳理
  • 【Linux】【命令】diff
  • 【JS】如何识别一个变量是不是数组对象
  • 【算法题】数组中只出现一次的两个数字
  • 【Python】Pandas基础操作手册(上)
  • 电能表预付费系统-标准传输规范(STS)(14)
  • 【数据结构】【单调栈】视野总和
  • 动态规划之打家劫舍
  • Python 类
  • 【计网】从零开始理解TCP协议 --- 拥塞控制机制,延迟应答机制,捎带应答,面向字节流
  • 【OD】【E卷】【真题】【100分】最大利润贪心的商人(PythonJavaJavaScriptC++C)
  • Docker无法拉取镜像解决办法
  • 程序员数学:用Python学透线性代数和微积分 中文目录
  • #P3014. 数字游戏
  • STM32F1+HAL库+FreeTOTS学习18——任务通知
  • Comfyui如何快速选出图像的高光和阴影 _ layerstyle节点
  • 动态规划58道算法题
  • 【Modern C++】特性学习与补漏
  • 作业2-线性回归的Matlab代码实现
  • SQL入门
  • RHCE——时间服务器
  • Java面试指南:Java基础介绍
  • Chromium127编译指南 Windows篇 - 编译前的准备(一)
  • 策略的结合——Actor-Critic算法求解冰湖游戏
  • code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED 证书过期