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

做淘宝客网站骗钱黄岐建网站

做淘宝客网站骗钱,黄岐建网站,关键词看片,百度信息流怎么投放Javascript 例子 修改页面内容 js 代码位置 script// js 代码 /script引入 js 脚本 script srcjs脚本路径/script注意#xff0c;到了框架之后#xff0c;引入方式会有不同 1. 变量与数据类型 声明变量 1) let ⭐️ l…Javascript 例子 修改页面内容 js 代码位置 script// js 代码 /script引入 js 脚本 script srcjs脚本路径/script注意到了框架之后引入方式会有不同 1. 变量与数据类型 声明变量 1) let ⭐️ let 变量名 值;let 声明的变量可以被多次赋值例如 let a 100; // 初始值是 100 a 200; // ok, 被重新赋值为 2002) const ⭐️ const 修饰的叫常量只能赋值一次 const b 300; // 初始值是 300 b 400; // error, 不能再次赋值const 并不意味着它引用的内容不可修改例如 const c [1,2,3]; c[2] 4; // ok, 数组内容被修改成 [1,2,4] c [5,6]; // error, 不能再次赋值3) var var 声明的变量可以被多次赋值例如 var f 100; f 200;基本类型 1,2) undefined 和 null 执行表达式或函数没有返回结果出现 undefined访问数组不存在的元素访问对象不存在的属性出现 undefined定义变量没有初始化出现 undefined 例 console.log(1); // 函数没有返回值, 结果是 undefined let a 10; // 表达式没有返回值, 结果是 undefined let b [1,2,3]; console.log(b[10]); // 数组未定义元素是 undefined let c {name:张三}; console.log(c.age); // 对象未定义属性是 undefined let d; console.log(d); // 变量未初始化是 undefined二者共同点 都没有属性、方法二者合称 Nullish 二者区别 undefined 由 js 产生null 由程序员提供 3) string ⭐️ js 字符串三种写法 let a hello; // 双引号 let b world; // 单引号 let c hello; // 反引号html 代码如下用 java 和 js 中的字符串如何表示 a href1.html超链接/ajava 显得比较繁琐 String s1 a href\1.html\超链接/a;String s2 a href1.html超链接/a;js 就比较灵活 let s1 a href1.html超链接/a;let s2 a href1.html超链接/a;模板字符串Template strings 需求拼接 URI 的请求参数如 /test?namezhangage18 /test?nameliage20传统方法拼接 let name ; // zhang li ... let age ; // 18 20 ...let uri /test?name name age age;模板字符串方式 let name ; // zhang li ... let age ; // 18 20 ...let uri /test?name${name}age${age};4,5) number 和 bigint⭐️ number 类型标识的是双精度浮动小数例如 10 / 3; // 结果 3.3333333333333335既然是浮点小数那么可以除零 10 / 0; // 结果 Infinity 正无穷大 -10 / 0; // 结果 -Infinity 负无穷大浮点小数都有运算精度问题例如 2.0 - 1.1; // 结果 0.8999999999999999字符串转数字 parseInt(10); // 结果是数字 10 parseInt(10.5); // 结果是数字 10, 去除了小数部分 parseInt(10) / 3; // 结果仍视为 number 浮点数, 因此结果为 3.3333333333333335parseInt(abc); // 转换失败结果是特殊值 NaN (Not a Number)要表示真正的整数需要用 bigint数字的结尾用 n 表示它是一个 bigint 类型 10n / 3n; // 结果 3n, 按整数除法处理6) boolean ⭐️ TruthyFalsy 在 js 中并不是 boolean 才能用于条件判断你可以在 if 语句中使用【数字】、【字符串】… 作为判断条件 let b 1;if(b) { // trueconsole.log(进入了); }这时就有一个规则当需要条件判断时这个值被当作 true 还是 false当作 true 的值归类为 truthy当作 false 的值归类为 falsy 下面值都是 falsy falseNullish (null, undefined)0, 0n, NaN 即长度为零的字符串 剩余的值绝大部分都是 truthy 有几个容易被当作 falsy 实际是 truthy 的 false, 0 即字符串的 false 和 字符串的零[] 空数组{} 空对象 对象类型 1) Function ⭐️⭐️ 定义函数 function 函数名(参数) {// 函数体return 结果; }例 function add(a, b) {return a b; }调用函数 函数名(实参);例 add(1, 2); // 返回 3js 中的函数调用特点对参数的类型和个数都没有限制例如 add(a, b); // 返回 ab add(4, 5, 6); // 返回 9, 第三个参数没有被用到, 不会报错 add(1); // 返回 NaN, 这时 b 没有定义是 undefined, undefined 做数学运算结果就是 NaN默认参数 java 中spring要实现默认参数的效果得这么做 RestController public class MyController {RequestMapping(/page)ResponseBodypublic void page(RequestParam(defaultValue1) int page, RequestParam(defaultValue10) int size){// ...} }js function pagination(page 1, size 10) {console.log(page, size); }匿名函数 语法 (function (参数) {// 函数体return 结果; })例 (function(a,b){return a b; })第一种场景定义完毕后立刻调用 (function(a,b){return a b; })(1,2)第二种场景作为其它对象的方法例如 页面有元素 p idp1点我啊/p此元素有一个 onclick 方法会在鼠标单击这个元素后被执行onclick 方法刚开始是 null需要赋值后才能使用 document.getElementById(p1).onclick (function(){console.log(鼠标单击了...); });箭头函数 (参数) {// 函数体return 结果; }如果没有参数() 还是要保留如果只有一个参数() 可以省略如果函数体内只有一行代码{} 可以省略如果这一行代码就是结果return 可以省略 例 document.getElementById(p1).onclick () console.log(aa);函数是对象 函数的本质是对象 以下形式在 js 中非常常见 可以参与赋值例具名函数也能参与赋值 function abc() {console.log(bb); }document.getElementById(p1).onclick abc;有属性、有方法执行 console.dir(abc)输出结果如下 ƒ abc()arguments: nullcaller: nulllength: 0name: abc➡prototype: {constructor: ƒ}[[FunctionLocation]]: VM1962:1➡[[Prototype]]: ƒ ()➡[[Scopes]]: Scopes[1]其中带有 f 标记的是方法不带的是属性 带有 ➡ 符号的可以继续展开限于篇幅省略了 带有 [[ ]] 的是内置属性不能访问只能查看 相对重要的是 [[Prototype]] 和 [[Scopes]] 会在后面继承和作用域时讲到 可以作为方法参数 function a() {console.log(a) }function b(fn) { // fn 将来可以是一个函数对象console.log(b)fn(); // 调用函数对象 }b(a)4. 可以作为方法返回值 function c() {console.log(c);function d() {console.log(d);}return d; }c()()函数作用域 函数可以嵌套js 代码中很常见只是嵌套的形式更多是匿名函数箭头函数 function a() {function b() { } }看下面的例子 function c() {var z 30; }var x 10; function a() {var y 20;function b() {// 看这里console.log(x, y);}b(); } a();以函数为分界线划定作用域所有函数之外是全局作用域查找变量时由内向外查找 在内层作用域找到变量就会停止查找不会再找外层所有作用域都找不到变量报错 作用域本质上是函数对象的属性可以通过 console.dir 来查看调试 闭包 var x 10; function a() {var y 20;function b() {console.log(x,y);}return b; } a()(); // 在外面执行了 b函数定义时它的作用域已经确定好了因此无论函数将来去了哪都能从它的作用域中找到当时那些变量 别被概念忽悠了闭包就是指函数能够访问自己的作用域中变量 let、var 与作用域 如果函数外层引用的是 let 变量那么外层普通的 {} 也会作为作用域边界最外层的 let 也占一个 script 作用域 let x 10; if(true) {let y 20;function b() {console.log(x,y);}console.dir(b); }如果函数外层引用的是 var 变量外层普通的 {} 不会视为边界 var x 10; if(true) {var y 20;function b() {console.log(x,y);}console.dir(b); }如果 var 变量出现了重名则他俩会被视为同一作用域中的同一个变量 var e 10; if(true) {var e 20;console.log(e); // 打印 20 } console.log(e); // 因为是同一个变量还是打印 20如果是 let则视为两个作用域中的两个变量 let e 10; if(true) {let e 20; console.log(e); // 打印 20 } console.log(e); // 打印 10要想里面的 e 和外面的 e 能区分开来最简单的办法是改成 let或者用函数来界定作用域范围 var e 10; if(true) {function b() {var e 20;console.log(e);}b(); } console.log(e); 2) Array ⭐️ 语法 // 创建数组 let arr [1,2,3]; // 获取数组元素 console.log(arr[0]); // 输出 1// 修改数组元素 array[0] 5; // 数组元素变成了 [5,2,3]// 遍历数组元素其中 length 是数组属性代表数组长度 for(let i 0; i arr.length; i) {console.log(arr[i]); }API push、shift、splice let arr [1,2,3]; arr.push(4); // 向数组尾部(右侧)添加元素, 结果 [1,2,3,4] arr.shift(); // 从数组头部(左侧)移除元素, 结果 [2,3,4] arr.splice(1,1); // 删除【参数1】索引位置的【参数2】个元素结果 [2,4]join let arr [a,b,c];arr.join(); // 默认使用【,】作为连接符结果 a,b,c arr.join(); // 结果 abc arr.join(-); // 结果 a-b-cmap、filter、forEach let arr [1,2,3,6];function a(i) { // 代表的新旧元素之间的变换规则return i * 10 }// arr.map(a) // 具名函数结果 [10,20,30,60]// arr.map( (i) {return i * 10} ); // 箭头函数 arr.map( i i * 10 ); // 箭头函数传给 map 的函数参数代表旧元素返回值代表新元素 map 的内部实现伪代码 function map(a) { // 参数是一个函数let narr [];for(let i 0; i arr.length; i) {let o arr[i]; // 旧元素let n a(o); // 新元素narr.push(n);}return narr; } filter 例子 let arr [1,2,3,6]; arr.filter( (i) i % 2 1 ); // 结果 [1,3]传给 filter 的函数参数代表旧元素返回 true 表示要留下的元素 forEach 例子 let arr [1,2,3,6];/*for(let i 0; i arr.length; i) {console.log(arr[i]); }*/arr.forEach( (i) console.log(i) );两个称呼 高阶函数mapfilterforEach回调函数例如作为参数传入的函数 3) Object ⭐️⭐️ 语法 let obj {属性名: 值,方法名: 函数,get 属性名() {},set 属性名(新值) {} }例1 let stu1 {name: 小明,age: 18,study: function(){console.log(this.name 爱学习);} }例2 let name 小黑; let age 20; let study function(){console.log(this.name 爱学习); }let stu2 { name, age, study }例3重点 let stu3 {name: 小白,age: 18,study(){console.log(this.name 爱学习);} }注意对象方法这么写仅限于对象内部 例4 let stu4 {_name: null, /*类似于java中私有成员变量*/get name() {console.log(进入了get);return this._name;},set name(name) {console.log(进入了set);this._name name;} }调用 getset stu4.name 小白console.log(stu4.name)特色属性增删 对比一下 Java 中的 Object Java 的 Object 是以类作为模板来创建对象不能脱离类模板的范围一个对象的属性、能用的方法都是确定好的js 的对象不需要什么模板它的属性和方法可以随时加减 let stu {name:张三}; stu.age 18; // 添加属性 delete stu.age; // 删除属性stu.study function() { // 添加方法console.log(this.name 在学习); }添加 getset需要借助 Object.definePropery let stu {_name:null};Object.defineProperty(stu, name, {get(){return this._name;},set(name){this._name name;} });参数1目标对象参数2属性名参数3getset 的定义 特色this 先来对 Java 中的 this 有个理解 public class TestMethod {static class Student {private String name;public Student(String name) {this.name name;}public void study(Student this, String subject) {System.out.println(this.name 在学习 subject);}}public static void main(String[] args) {Student stu new Student(小明);// 下面的代码本质上是执行 study(stu, java)因此 this 就是 stustu.study(java); } }Java 中的 this 是个隐式参数Java 中我们说 this 代表的就是调用方法的那个对象 js 中的 this 也是隐式参数但它与函数运行时上下文相关 例如一个“落单”的函数 function study(subject) {console.log(this.name 在学习 subject) }测试一下 study(js); // 输出 在学习 js这是因为此时函数执行全局对象 window 被当作了 thiswindow 对象的 name 属性是空串 同样的函数如果作为对象的方法 let stu {name:小白,study }这种情况下会将当前对象作为 this stu.study(js); // 输出 小白在学习 js还可以动态改变 this let stu {name:小黑}; study.call(stu, js); // 输出 小黑在学习 js这回 study 执行时就把 call 的第一个参数 stu 作为 this 一个例外是在箭头函数内出现的 this以外层 this 理解 用匿名函数 let stu {name: 小花,friends: [小白,小黑,小明],play() {this.friends.forEach(function(e){console.log(this.name 与 e 在玩耍);});} } stu.play()this.name 所在的函数是【落单】的函数因此 this 代表 window 输出结果为 与小白在玩耍 与小黑在玩耍 与小明在玩耍用箭头函数 let stu {name: 小花,friends: [小白,小黑,小明],play() {this.friends.forEach(e {console.log(this.name 与 e 在玩耍);})} }this.name 所在的函数是箭头函数因此 this 要看它外层的 play 函数play 又是属于 stu 的方法因此 this 代表 stu 对象 输出结果为 小花与小白在玩耍 小花与小黑在玩耍 小花与小明在玩耍不用箭头函数的做法 let stu {name: 小花,friends: [小白,小黑,小明],play() {let me this;this.friends.forEach(function(e){console.log(me.name 与 e 在玩耍);});} }特色原型继承 let father {f1: 父属性,m1: function() {console.log(父方法);} }let son Object.create(father);console.log(son.f1); // 打印 父属性 son.m1(); // 打印 父方法father 是父对象son 去调用 .m1 或 .f1 时自身对象没有就到父对象找son 自己可以添加自己的属性和方法son 里有特殊属性 __proto__ 代表它的父对象js 术语 son 的原型对象不同浏览器对打印 son 的 __proto__ 属性时显示不同 Edge 打印 console.dir(son) 显示 [[Prototype]]Firefox 打印 console.dir(son) 显示 prototype 特色基于函数的原型继承 出于方便的原因js 又提供了一种基于函数的原型继承 函数职责 负责创建子对象给子对象提供属性、方法功能上相当于构造方法 函数有个特殊的属性 prototype它就是函数创建的子对象的父对象 **注意**名字有差异这个属性的作用就是为新对象提供原型 function cons(f2) {// 创建子对象(this), 给子对象提供属性和方法this.f2 f2;this.m2 function () {console.log(子方法);} } // cons.prototype 就是父对象 cons.prototype.f1 父属性; cons.prototype.m1 function() {console.log(父方法); }配合 new 关键字创建子对象 let son new cons(子属性)子对象的 __proto__ 就是函数的 prototype 属性 JSON 之前我们讲 http 请求格式时讲过 json 这种数据格式它的语法看起来与 js 对象非常相似例如 一个 json 对象可以长这样 {name:张三,age:18 }一个 js 对象长这样 {name:张三,age:18 }那么他们的区别在哪儿呢我总结了这么几点 本质不同 json 对象本质上是个字符串它的职责是作为客户端和服务器之间传递数据的一种格式它的属性只是样子货js 对象是切切实实的对象可以有属性方法 语法细节不同 json 中只能有 null、true|false、数字、字符串只有双引号、对象、数组json 中不能有除以上的其它 js 对象的特性如方法等json 中的属性必须用双引号引起来 json 字符串与 js 对象的转换 JSON.parse(json字符串); // 返回js对象 JSON.stringify(js对象); // 返回json字符串动态类型 静态类型语言如 Java值有类型变量也有类型、赋值给变量时类型要相符 int a 10; String b abc;int c abc; // 错误而 js 属于动态类型语言值有类型但变量没有类型赋值给变量时没要求 例如 let a 200;let b 100; b abc; b true;动态类型看起来比较灵活但变量没有类型会给后期维护带来困难例如 function test(obj) {// obj 的类型未知必须根据不同类型做出相应的容错处理 }运算符与表达式 - * / % ** - * / % ** --位运算、移位运算 ! ! ⭐️ || ! ⭐️?? ?. ⭐️... ⭐️解构赋值 ⭐️ 1) 严格相等运算符用作逻辑判等 1 1 // 返回 true 1 1 // 返回 true会先将右侧的字符串转为数字再做比较 1 1 // 返回 false类型不等直接返回 falsetypeof 查看某个值的类型 typeof 1 // 返回 number typeof 1 // 返回 string2) || 需求如果参数 n 没有传递给它一个【男】 推荐做法 function test(n 男) {console.log(n); }你可能的做法 function test(n) {if(n undefined) {n 男;}console.log(n); }还可能是这样 function test(n) {n (n undefined) ? 男 : n;console.log(n); }一些老旧代码中可能的做法不推荐 function test(n) {n n || 男;console.log(n); }它的语法是 值1 || 值2如果值1 是 Truthy返回值1如果值1 是 Falsy 返回值 2 3) ?? 与 ?. ?? 需求如果参数 n 没有传递或是 null给它一个【男】 如果用传统办法 function test(n) {if(n undefined || n null) {n 男;}console.log(n); }用 ?? function test(n) {n n ?? 男;console.log(n); }语法 值1 ?? 值2值1 是 nullish返回值2值1 不是 nullish返回值1 ?. 需求函数参数是一个对象可能包含有子属性 例如参数可能是 let stu1 {name:张三,address: {city: 北京} };let stu2 {name:李四 }let stu3 {name:李四,address: null }现在要访问子属性有问题 function test(stu) {console.log(stu.address.city) }现在希望当某个属性是 nullish 时短路并返回 undefined可以用 ?. function test(stu) {console.log(stu.address?.city) }用传统办法 function test(stu) {if(stu.address undefined || stu.address null) {console.log(undefined);return;}console.log(stu.address.city) }4) … 展开运算符 作用1打散数组把元素传递给多个参数 let arr [1,2,3];function test(a,b,c) {console.log(a,b,c); }需求把数组元素依次传递给函数参数 传统写法 test(arr[0],arr[1],arr[2]); // 输出 1,2,3展开运算符写法 test(...arr); // 输出 1,2,3打散可以理解为【去掉了】数组外侧的中括号只剩下数组元素 作用2复制数组或对象 数组 let arr1 [1,2,3]; let arr2 [...arr1]; // 复制数组对象 let obj1 {name:张三, age: 18};let obj2 {...obj1}; // 复制对象注意展开运算符复制属于浅拷贝例如 let o1 {name:张三, address: {city: 北京} }let o2 {...o1};作用3合并数组或对象 合并数组 let a1 [1,2]; let a2 [3,4];let b1 [...a1,...a2]; // 结果 [1,2,3,4] let b2 [...a2,5,...a1] // 结果 [3,4,5,1,2]合并对象 let o1 {name:张三}; let o2 {age:18}; let o3 {name:李四};let n1 {...o1, ...o2}; // 结果 {name:张三,age:18}let n2 {...o3, ...o2, ...o1}; // 结果{name:李四,age:18}复制对象时出现同名属性后面的会覆盖前面的 5) [] {} 解构赋值 [] 用在声明变量时 let arr [1,2,3];let [a, b, c] arr; // 结果 a1, b2, c3用在声明参数时 let arr [1,2,3];function test([a,b,c]) {console.log(a,b,c) // 结果 a1, b2, c3 }test(arr); {} 用在声明变量时 let obj {name:张三, age:18};let {name,age} obj; // 结果 name张三, age18用在声明参数时 let obj {name:张三, age:18};function test({name, age}) {console.log(name, age); // 结果 name张三, age18 }test(obj)3. 控制语句 if ... elseswitchwhiledo ... whileforfor ... in ⭐️for ... of ⭐️try ... catch ⭐️ 1) for in 主要用来遍历对象 let father {name:张三, age:18, study:function(){}};for(const n in father) {console.log(n); }其中 const n 代表遍历出来的属性名注意1方法名也能被遍历出来它其实也算一种特殊属性注意2遍历子对象时父对象的属性会跟着遍历出来 let son Object.create(father); son.sex 男;for(const n in son) {console.log(n); }注意3在 for in 内获取属性值要使用 [] 语法而不能用 . 语法 for(const n in son) {console.log(n, son[n]); }2) for of 主要用来遍历数组也可以是其它可迭代对象如 MapSet 等 let a1 [1,2,3];for(const i of a1) {console.log(i); }let a2 [{name:张三, age:18},{name:李四, age:20},{name:王五, age:22} ];for(const obj of a2) {console.log(obj.name, obj.age); }for(const {name,age} of a2) {console.log(name, age); }3) try catch let stu1 {name:张三, age:18, address: {city:北京}}; let stu2 {name:张三, age:18};function test(stu) {try {console.log(stu.address.city) } catch(e) {console.log(出现了异常, e.message)} finally {console.log(finally);} }Vue2 使用 vite 创建 ## 创建工程 npm init vite-app project-name ## 进入工程目录 cd project-name ## 安装依赖 npm install ## 运行 npm run devVue 项目结构 ├─assets ├─components ├─router ├─store └─viewsassets - 静态资源components - 可重用组件router - 路由store - 数据共享views - 视图组件 以后还会添加 api - 跟后台交互发送 fetch、xhr 请求接收响应plugins - 插件 vue大致流程 核心是create那 main.js是首先运行的文件运行创建节点到index.html 2) Vue 组件 Vue 的组件文件以 .vue 结尾每个组件由三部分组成 template/templatescript/scriptstyle/styletemplate 模板部分由它生成 html 代码script 代码部分控制模板的数据来源和行为style 样式部分一般不咋关心 入口组件是 App.vue 先删除原有代码来个 Hello, World 例子 templateh1{{msg}}/h1 /templatescript export default {data() {return {msg: Hello, Vue!}} } /script解释 export default 导出组件对象供 main.js 导入使用这个对象有一个 data 方法返回一个对象给 template 提供数据{{}} 在 Vue 里称之为插值表达式用来绑定 data 方法返回的对象属性绑定的含义是数据发生变化时页面显示会同步变化 文本插值 templatedivh1{{ name }}/h1h1{{ age 60 ? 老年 : 青年 }}/h1/div /template script const options {data: function () {return { name: 张三, age: 70 };} }; export default options; /script{{}} 里只能绑定一个属性绑定多个属性需要用多个 {{}} 分别绑定template 内只能有一个根元素插值内可以进行简单的表达式计算 属性绑定 templatedivdivinput typetext v-bind:valuename/divdivinput typedate v-bind:valuebirthday/divdivinput typetext :valueage/div/div /template script const options {data: function () {return { name: 王五, birthday: 1995-05-01, age: 20 };} }; export default options; /script简写方式可以省略 v-bind 只保留冒号 事件绑定 !-- 事件绑定 -- templatedivdivinput typebutton value点我执行m1 v-on:clickm1/divdivinput typebutton value点我执行m2 clickm2/divdiv{{count}}/div/div /template script const options {data: function () {return { count: 0 };},methods: {m1() {this.count ;console.log(m1)},m2() {this.count --;console.log(m2)}} }; export default options; /script简写方式可以把 v-on: 替换为 在 methods 方法中的 this 代表的是 data 函数返回的数据对象 双向绑定 templatedivdivlabel for请输入姓名/labelinput typetext v-modelname/divdivlabel for请输入年龄/labelinput typetext v-modelage/divdivlabel for请选择性别/label男 input typeradio value男 v-modelsex女 input typeradio value女 v-modelsex/divdivlabel for请选择爱好/label游泳 input typecheckbox value游泳 v-modelfav打球 input typecheckbox value打球 v-modelfav健身 input typecheckbox value健身 v-modelfav/div/div /template script const options {data: function () {return { name: , age: null, sex:男 , fav:[打球]};},methods: {} }; export default options; /script用 v-model 实现双向绑定即 javascript 数据可以同步到表单标签反过来用户在表单标签输入的新值也会同步到 javascript 这边 双向绑定只适用于表单这种带【输入】功能的标签其它标签的数据绑定单向就足够了复选框这种标签双向绑定的 javascript 数据类型一般用数组 计算属性 !-- 计算属性 -- templatedivh2{{fullName}}/h2h2{{fullName}}/h2h2{{fullName}}/h2h1{{m1()}}/h1/div /template script const options {data: function () {return { firstName: 三, lastName: 张 };},methods: {m1() {console.log(进入了 m1)return this.lastName this.firstName;}},computed: {fullName() {console.log(进入了 fullName)return this.lastName this.firstName;}} }; export default options;普通方法调用必须加 ()没有缓存功能计算属性使用时就把它当属性来用不加 ()有缓存功能 一次计算后会将结果缓存下次再计算时只要数据没有变化不会重新计算直接返回缓存结果 axios axios 它的底层是用了 XMLHttpRequestxhr方式发送请求和接收响应xhr 相对于之前讲过的 fetch api 来说功能更强大但由于是比较老的 api不支持 Promiseaxios 对 xhr 进行了封装使之支持 Promise并提供了对请求、响应的统一拦截功能 安装 npm install axios -S导入 import axios from axiosaxios 默认导出一个对象这里的 import 导入的就是它默认导出的对象 方法 请求备注axios.get(url[, config])⭐️axios.delete(url[, config])axios.head(url[, config])axios.options(url[, config])axios.post(url[, data[, config]])⭐️axios.put(url[, data[, config]])axios.patch(url[, data[, config]]) config - 选项对象、例如查询参数、请求头…data - 请求体数据、最常见的是 json 格式数据get、head 请求无法携带请求体这应当是浏览器的限制所致xhr、fetch api 均有限制options、delete 请求可以通过 config 中的 data 携带请求体 例子 templatedivinput typebutton value获取远程数据 clicksendReq()/div /template script import axios from axios const options {methods: {async sendReq() {// 1. 演示 get, post// const resp await axios.post(/api/a2);// 2. 发送请求头// const resp await axios.post(/api/a3,{},{// headers:{// Authorization:abc// }// });// 3. 发送请求时携带查询参数 ?namexxxagexxx// const name encodeURIComponent();// const age 18;// const resp await axios.post(/api/a4?name${name}age${age});// 不想自己拼串、处理特殊字符、就用下面的办法// const resp await axios.post(/api/a4, {}, {// params: {// name:,// age: 20// }// });// 4. 用请求体发数据格式为 urlencoded// const params new URLSearchParams();// params.append(name, 张三);// params.append(age, 24)// const resp await axios.post(/api/a4, params);// 5. 用请求体发数据格式为 multipart// const params new FormData();// params.append(name, 李四);// params.append(age, 30);// const resp await axios.post(/api/a5, params);// 6. 用请求体发数据格式为 jsonconst resp await axios.post(/api/a5json, {name: 王五,age: 50});console.log(resp);}} }; export default options; /script创建实例 const _axios axios.create(config);axios 对象可以直接使用但使用的是默认的设置用 axios.create 创建的对象可以覆盖默认设置config 见下面说明 常见的 config 项有 名称含义baseURL将自动加在 url 前面headers请求头类型为简单对象params跟在 URL 后的请求参数类型为简单对象或 URLSearchParamsdata请求体类型有简单对象、FormData、URLSearchParams、File 等withCredentials跨域时是否携带 Cookie 等凭证默认为 falseresponseType响应类型默认为 json 例 const _axios axios.create({baseURL: http://localhost:8080, //请求方式跨域withCredentials: true }); await _axios.post(/api/a6set) await _axios.post(/api/a6get)生产环境希望 xhr 请求不走代理可以用 baseURL 统一修改希望跨域请求携带 cookie需要配置 withCredentials: true服务器也要配置 allowCredentials true否则浏览器获取跨域返回的 cookie 时会报错 跨域问题解决 public class App implements WebMvcConfigurer {Beanpublic LoginInterceptor loginInterceptor() {return new LoginInterceptor();}Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor()).addPathPatterns(/api/**);}Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping(/**).allowedOrigins(http://localhost:7070).allowCredentials(true);} 响应格式 名称含义data响应体数据 ⭐️status状态码 ⭐️headers响应头 200 表示响应成功400 请求数据不正确 ageabc401 身份验证没通过403 没有权限404 资源不存在405 不支持请求方式 post500 服务器内部错误 请求拦截器 类似于trycatch 异常捕获 _axios.interceptors.request.use(function(config) {// 比如在这里添加统一的 headersreturn config;},function(error) {return Promise.reject(error);} );响应拦截器 _axios.interceptors.response.use(function(response) {// 2xx 范围内走这里return response;},function(error) {// 超出 2xx, 比如 4xx, 5xx 走这里return Promise.reject(error);} );脚手架中必有的 上述跨域部分内容相当于一个脚手架必须要有的 ​⭐️​​⭐️​​⭐️​ import axios from axios const _axios axios.create({// baseURL: http://localhost:8080,withCredentials: true });// 9. 拦截器 _axios.interceptors.request.use(function (config) {// 比如在这里添加统一的 headersconfig.headers {Authorization: aaa.bbb.ccc}return config;},function (error) {return Promise.reject(error);} );_axios.interceptors.response.use(function (response) {// 2xx 范围内走这里return response;},function (error) {if (error.response?.status 400) {console.log(请求参数不正确);return Promise.resolve(400);} else if (error.response?.status 401) {console.log(跳转至登录页面);return Promise.resolve(401);} else if (error.response?.status 404) {console.log(资源未找到);return Promise.resolve(404);}// 超出 2xx, 比如 4xx, 5xx 走这里return Promise.reject(error);} );export default _axios;条件渲染 templatedivinput typebutton value获取远程数据 clicksendReq()div classtitle学生列表/divdiv classtheaddiv classrow bolddiv classcol编号/divdiv classcol姓名/divdiv classcol性别/divdiv classcol年龄/div/div/divdiv classtbodydiv classrow v-ifstudents.length 0显示学生数据/divdiv classrow v-else暂无学生数据/div/div/div /template script import axios from ../util/myaxios const options {data: function() {return {students: []};},methods : {async sendReq() {const resp await axios.get(/api/students);console.log(resp.data.data)this.students resp.data.data;}} }; export default options; /script style scopeddiv {font-family: 华文行楷;font-size: 20px;}.title {margin-bottom: 10px;font-size: 30px;color: #333;text-align: center;}.row {background-color: #fff;display: flex;justify-content: center;}.col {border: 1px solid #f0f0f0;width: 15%;height: 35px;text-align: center;line-height: 35px;}.bold .col {background-color: #f1f1f1;} /style列表渲染 templatediv!-- input typebutton value获取远程数据 clicksendReq() --div classtitle学生列表/divdiv classtheaddiv classrow bolddiv classcol编号/divdiv classcol姓名/divdiv classcol性别/divdiv classcol年龄/div/div/divdiv classtbodydiv v-ifstudents.length 0div classrow v-fors of students :keys.iddiv classcol{{s.id}}/divdiv classcol{{s.name}}/divdiv classcol{{s.sex}}/divdiv classcol{{s.age}}/div/div/divdiv classrow v-else暂无学生数据/div/div/div /template script import axios from ../util/myaxios const options {mounted: function(){this.sendReq()},data: function() {return {students: []};},methods : {async sendReq() {const resp await axios.get(/api/students);console.log(resp.data.data)this.students resp.data.data;}} }; export default options; /script style scopeddiv {font-family: 华文行楷;font-size: 20px;}.title {margin-bottom: 10px;font-size: 30px;color: #333;text-align: center;}.row {background-color: #fff;display: flex;justify-content: center;}.col {border: 1px solid #f0f0f0;width: 15%;height: 35px;text-align: center;line-height: 35px;}.bold .col {background-color: #f1f1f1;} /stylev-if 和 v-for 不能用于同一个标签v-for 需要配合特殊的标签属性 key 一起使用并且 key 属性要绑定到一个能起到唯一标识作用的数据上本例绑定到了学生编号上options 的 mounted 属性对应一个函数此函数会在组件挂载后准备就绪被调用可以在它内部发起请求去获取学生数据 重用组件 一般都是使用el组件库 按钮组件 templatediv classbutton :class[type,size]aslot/slotb/div /template script const options {props: [type, size] }; export default options; /script注意省略了样式部分 使用组件 templatedivh1父组件/h1my-button typeprimary sizesmall1/my-buttonmy-button typedanger sizemiddle2/my-buttonmy-button typesuccess sizelarge3/my-button/div /template script import MyButton from ../components/MyButton.vue const options {components: {MyButton} }; export default options; /script2. Vue 进阶 1) ElementUI 安装 npm install element-ui -S引入组件 import Element from element-ui import element-ui/lib/theme-chalk/index.cssVue.use(Element)测试在自己的组件中使用 ElementUI 的组件 el-button按钮/el-button2) Vue-Router vue 属于单页面应用所谓的路由就是根据浏览器路径不同用不同的视图组件替换这个页面内容展示类似于gateway 配置路由 新建一个路由 js 文件例如 src/router/example14.js内容如下 import Vue from vue import VueRouter from vue-router import ContainerView from /views/example14/ContainerView.vue import LoginView from /views/example14/LoginView.vue import NotFoundView from /views/example14/NotFoundView.vueVue.use(VueRouter)const routes [{path:/,component: ContainerView},{path:/login,component: LoginView},{path:/404,component: NotFoundView} ]const router new VueRouter({routes })export default router最重要的就是建立了【路径】与【视图组件】之间的映射关系本例中映射了 3 个路径与对应的视图组件 在 main.js 中采用我们的路由 js import Vue from vue import e14 from ./views/Example14View.vue import router from ./router/example14 // 修改这里 import store from ./store import Element from element-ui import element-ui/lib/theme-chalk/index.cssVue.config.productionTip falseVue.use(Element) new Vue({router,store,render: h h(e14) }).$mount(#app)根组件是 Example14View.vue内容为 templatediv classallrouter-view/router-view/div /template样式略其中 router-view 起到占位作用改变路径后这个路径对应的视图组件就会占据 router-view 的位置替换掉它之前的内容 动态导入 import Vue from vue import VueRouter from vue-routerVue.use(VueRouter)const routes [{path:/,component: () import(/views/example14/ContainerView.vue)},{path:/login,component: () import(/views/example14/LoginView.vue)},{path:/404,component: () import(/views/example14/NotFoundView.vue)} ]const router new VueRouter({routes })export default router静态导入是将所有组件的 js 代码打包到一起如果组件非常多打包后的 js 文件会很大影响页面加载速度动态导入是将组件的 js 代码放入独立的文件用到时才加载 嵌套路由 组件内再要切换内容就需要用到嵌套路由子路由下面的例子是在【ContainerView 组件】内定义了 3 个子路由 const routes [{path:/,component: () import(/views/example14/ContainerView.vue),redirect: /c/p1,children: [{ path:c/p1,component: () import(/views/example14/container/P1View.vue)},{ path:c/p2,component: () import(/views/example14/container/P2View.vue)},{ path:c/p3,component: () import(/views/example14/container/P3View.vue)}]},{path:/login,component: () import(/views/example14/LoginView.vue)},{path:/404,component: () import(/views/example14/NotFoundView.vue)},{path:*,redirect: /404} ]子路由变化切换的是【ContainerView 组件】中 router-view/router-view 部分的内容 templatediv classcontainerrouter-view/router-view/div /templateredirect 可以用来重定向跳转到一个新的地址path 的取值为 * 表示匹配不到其它 path 时就会匹配它 ElementUI 布局 通常主页要做布局下面的代码是 ElementUI 提供的【上-【左-右】】布局 templatediv classcontainerel-containerel-header/el-headerel-containerel-aside width200px/el-asideel-mainrouter-view/router-view/el-main/el-container/el-container/div /template路由跳转 标签式 el-aside width200pxrouter-link to/c1/p1P1/router-linkrouter-link to/c1/p2P2/router-linkrouter-link to/c1/p3P3/router-link /el-aside编程式 el-headerel-button typeprimary iconel-icon-edit circle sizemini clickjump(/c1/p1)/el-buttonel-button typesuccess iconel-icon-check circle sizemini clickjump(/c1/p2)/el-buttonel-button typewarning iconel-icon-star-off circle sizemini clickjump(/c1/p3)/el-button /el-headerjump 方法 script const options {methods : {jump(url) {this.$router.push(url);}} } export default options; /script其中 this.$router 是拿到路由对象push 方法根据 url 进行跳转 导航菜单 el-menu router background-color#545c64 text-color#fff active-text-color#ffd04bel-submenu index/c1span slottitlei classel-icon-platform-eleme/i菜单1/spanel-menu-item index/c1/p1子项1/el-menu-itemel-menu-item index/c1/p2子项2/el-menu-itemel-menu-item index/c1/p3子项3/el-menu-item/el-submenuel-menu-item index/c2span slottitlei classel-icon-phone/i菜单2/span/el-menu-itemel-menu-item index/c3span slottitlei classel-icon-star-on/i菜单3/span/el-menu-item /el-menu图标和菜单项文字建议用 span slottitle/span 包裹起来el-menu 标签上加上 router 属性表示结合导航菜单与路由对象此时就可以利用菜单项的 index 属性来路由跳转 动态路由与菜单 将菜单、路由信息仅主页的存入数据库中 insert into menu(id, name, pid, path, component, icon) values(101, 菜单1, 0, /m1, null, el-icon-platform-eleme),(102, 菜单2, 0, /m2, null, el-icon-delete-solid),(103, 菜单3, 0, /m3, null, el-icon-s-tools),(104, 菜单4, 0, /m4, M4View.vue, el-icon-user-solid),(105, 子项1, 101, /m1/c1, C1View.vue, el-icon-s-goods),(106, 子项2, 101, /m1/c2, C2View.vue, el-icon-menu),(107, 子项3, 102, /m2/c3, C3View.vue, el-icon-s-marketing),(108, 子项4, 102, /m2/c4, C4View.vue, el-icon-s-platform),(109, 子项5, 102, /m2/c5, C5View.vue, el-icon-picture),(110, 子项6, 103, /m3/c6, C6View.vue, el-icon-upload),(111, 子项7, 103, /m3/c7, C7View.vue, el-icon-s-promotion);不同的用户查询的的菜单、路由信息是不一样的 例如访问 /api/menu/admin 返回所有的数据 [{id: 102,name: 菜单2,icon: el-icon-delete-solid,path: /m2,pid: 0,component: null},{id: 107,name: 子项3,icon: el-icon-s-marketing,path: /m2/c3,pid: 102,component: C3View.vue},{id: 108,name: 子项4,icon: el-icon-s-platform,path: /m2/c4,pid: 102,component: C4View.vue},{id: 109,name: 子项5,icon: el-icon-picture,path: /m2/c5,pid: 102,component: C5View.vue} ]访问 /api/menu/wang 返回 [{id: 103,name: 菜单3,icon: el-icon-s-tools,path: /m3,pid: 0,component: null},{id: 110,name: 子项6,icon: el-icon-upload,path: /m3/c6,pid: 103,component: C6View.vue},{id: 111,name: 子项7,icon: el-icon-s-promotion,path: /m3/c7,pid: 103,component: C7View.vue} ]前端根据他们身份不同动态添加路由和显示菜单 动态路由 export function addServerRoutes(array) {for (const { id, path, component } of array) {if (component ! null) {// 动态添加路由// 参数1父路由名称// 参数2路由信息对象router.addRoute(c, {path: path,name: id,component: () import(/views/example15/container/${component})});}} }js 这边只保留几个固定路由如主页、404 和 login以上方法执行时将服务器返回的路由信息加入到名为 c 的父路由中去这里要注意组件路径前面 /views 是必须在 js 这边完成拼接的否则 import 函数会失效 重置路由 在用户注销时应当重置路由 export function resetRouter() {router.matcher new VueRouter({ routes }).matcher }页面刷新 页面刷新后会导致动态添加的路由失效解决方法是将路由数据存入 sessionStorage script import axios from /util/myaxios import {resetRouter, addServerRoutes} from /router/example15 const options {data() {return {username: admin}},methods: {async login() { resetRouter(); // 重置路由 const resp await axios.get(/api/menu/${this.username})const array resp.data.data;// localStorage 即使浏览器关闭存储的数据仍在// sessionStorage 以标签页为单位关闭标签页时数据被清除sessionStorage.setItem(serverRoutes, JSON.stringify(array))addServerRoutes(array); // 动态添加路由this.$router.push(/);}} } export default options; /script页面刷新重新创建路由对象时从 sessionStorage 里恢复路由数据 const router new VueRouter({routes })// 从 sessionStorage 中恢复路由数据 const serverRoutes sessionStorage.getItem(serverRoutes); if(serverRoutes) {const array JSON.parse(serverRoutes);addServerRoutes(array) // 动态添加路由 }动态菜单 代码部分 script const options {mounted() {const serverRoutes sessionStorage.getItem(serverRoutes);const array JSON.parse(serverRoutes);const map new Map();for(const obj of array) {map.set(obj.id, obj);}const top [];for(const obj of array) {const parent map.get(obj.pid);if(parent) {parent.children ?? [];parent.children.push(obj);} else {top.push(obj);}}this.top top;},data() {return {top: []}} } export default options; /script菜单部分 el-menu router background-color#545c64 text-color#fff active-text-color#ffd04b :unique-openedtruetemplate v-form1 of top el-submenu v-ifm1.children :keym1.id :indexm1.pathspan slottitlei :classm1.icon/i {{m1.name}}/spanel-menu-item v-form2 of m1.children :keym2.id :indexm2.pathspan slottitlei :classm2.icon/i {{m2.name}}/span/el-menu-item/el-submenu el-menu-item v-else :keym1.id :indexm1.pathspan slottitlei :classm1.icon/i {{m1.name}}/span/el-menu-item/template /el-menu没有考虑递归菜单问题认为菜单只有两级 3) Vuex 入门 vuex 可以在多个组件之间共享数据并且共享的数据是【响应式】的即数据的变更能及时渲染到模板 与之对比 localStorage 与 sessionStorage 也能共享数据但缺点是数据并非【响应式】 首先需要定义 state 与 mutations 他们一个用来读取共享数据一个用来修改共享数据 src/store/index.js import Vue from vue import Vuex from vuexVue.use(Vuex)/*读取数据走 state, getters修改数据走 mutations, actions */ export default new Vuex.Store({state: {name: ,age: 18},getters: {},mutations: {updateName(state, name) {state.name name;}},actions: {},modules: {} })修改共享数据 templatediv classpel-input placeholder请修改用户姓名 sizemini v-modelname/el-inputel-button typeprimary sizemini clickupdate()修改/el-button/div /template script const options {methods: {update(){this.$store.commit(updateName, this.name);}},data () {return {name:}} } export default options; /scriptmutations 方法不能直接调用只能通过 store.commit(mutation方法名, 参数) 来间接调用 读取共享数据 templatediv classcontainerel-containerel-headerdiv classt欢迎您{{ $store.state.name }}, {{ $store.state.age }}/div/el-headerel-containerel-aside width200px/el-asideel-mainrouter-view/router-view/el-main/el-container/el-container/div /templatemapState 每次去写 $store.state.name 这样的代码显得非常繁琐可以用 vuex 帮我们生成计算属性 templatediv classcontainerel-containerel-headerdiv classt欢迎您{{ name }}, {{ age }}/div/el-headerel-containerel-aside width200px/el-asideel-mainrouter-view/router-view/el-main/el-container/el-container/div /template script import { mapState } from vuex const options {computed: {...mapState([name, age])} } export default options; /scriptmapState 返回的是一个对象对象内包含了 name() 和 age() 的这两个方法作为计算属性此对象配合 ... 展开运算符填充入 computed 即可使用 mapMutations templatediv classpel-input placeholder请修改用户姓名 sizemini v-modelname/el-inputel-button typeprimary sizemini clickupdateName(name)修改/el-button/div /template script import {mapMutations} from vuex const options {methods: {...mapMutations([updateName])},data () {return {name:}} } export default options; /script类似的调用 mutation 修改共享数据也可以简化mapMutations 返回的对象中包含的方法就会调用 store.commit() 来执行 mutation 方法注意参数传递略有不同 actions mutations 方法内不能包括修改不能立刻生效的代码否则会造成 Vuex 调试工具工作不准确必须把这些代码写在 actions 方法中 import Vue from vue import Vuex from vuexVue.use(Vuex)/*读取数据走 state, getters修改数据走 mutations, actions */ import axios from /util/myaxios export default new Vuex.Store({state: {name: ,age: 18},getters: {},mutations: {updateName(state, name) {state.name name;},// 错误的用法如果在mutations方法中包含了异步操作会造成开发工具不准确/* async updateServerName(state) {const resp await axios.get(/api/user);const {name, age} resp.data.data;state.name name;state.age age;} */updateServerName(state, user) {const { name, age } user;state.name name;state.age age;}},actions: {async updateServerName(context) {const resp await axios.get(/api/user);context.commit(updateServerName, resp.data.data)}},modules: {} })首先应当调用 actions 的 updateServerName 获取数据然后再由它间接调用 mutations 的 updateServerName 更新共享数据 页面使用 actions 的方法可以这么写 templatediv classpel-button typeprimary sizeminiclickupdateServerName()从服务器获取数据,存入store/el-button/div /template script import { mapActions } from vuex const options {methods: {...mapActions([updateServerName])} } export default options; /scriptmapActions 会生成调用 actions 中方法的代码 调用 actions 的代码内部等价于它返回的是 Promise 对象可以用同步或异步方式接收结果 this.$store.dispatch(action名称, 参数)Vue3 React
http://www.sadfv.cn/news/9980/

相关文章:

  • 杭州模板建站定制岳阳网站建设收费标准
  • 设备管理系统网站模板做pc端软件可以参考那些网站
  • 百度排名 网站标题wordpress metro手机主题
  • 关于建设公司网站的议题上市公司网站建设要求
  • 建设工程监理 精品课网站用织梦做网站都需要用什么
  • 增城网站建设价格wordpress 外贸模板
  • 哪个网可以网站备案门店充值会员卡系统
  • 无锡餐饮网站建设搜索引擎调词软件
  • 网站建设程序做哪些个人特种证件查询网站
  • 购物网站建设怎么样济南市建设银行网站
  • 建设广州公司网站wordpress装在根目录文件夹中_如何通过域名直接访问?
  • 什么网站建设德国著名的外贸公司地址
  • 怎样做团购网站没有公司地址怎么注册公司
  • 专业苏州网站建设公司哪家好免费资源源码网站
  • 英文网站注册迁西网站定制
  • 值得浏览的国外网站大连网站建设流程图
  • 网站的数据运营怎么做制作网络网站
  • 响应式网站制作wordpress js加载位置
  • 电子商务网站建设与管理期末答案上海备案证查询网站
  • 做线上网站需要钱吗食品网站建设的目的
  • 临沭有做网站的吗深圳设计公司排名深圳市广告公司
  • 网站设计优化永久免费手机网站自助建站
  • 网站功能价格表谢岗镇仿做网站
  • 网站设计的技巧织梦批量修改网站源代码
  • wordpress总是跳出淘宝排名优化公司口碑哪家好
  • 做暧暧视频网站下载广告策划案
  • 网站用什么主机网站建设 招聘需求
  • 京东网站建设的主旨贝锐免费域名
  • 微网站搭建网站怎么做301跳转
  • 网站建设初学软件网络舆情处置的五个步骤