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

森网站建设粮油移动端网页设计素材

森网站建设,粮油移动端网页设计素材,专业团队黑人,微网站开发手机模拟器它是一种脚本语言#xff0c;可以用来更改页面内容#xff0c;控制多媒体#xff0c;制作图像、动画等等 js 代码位置 script// js 代码 /script引入 js 脚本#xff0c;在js脚本中写js代码 script srcjs脚本路径/script注…它是一种脚本语言可以用来更改页面内容控制多媒体制作图像、动画等等 js 代码位置 script// js 代码 /script引入 js 脚本在js脚本中写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;能使用let跟var的情况下尽量使用let因为var容易有作用域问题。 基本类型 1,2) undefined 和 null 执行表达式或函数没有返回结果出现 undefinedconsole.log(1)1 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 和 字符串的零[] 空数组{} 空对象 7) symbol 很少使用 对象类型 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) //打印 b a可以作为方法返回值 function c() {console.log(c);function d() {console.log(d);}return d; }c()() //打印 c d因为c中定义的d函数没有被c调用在调用c函数时先打印了c字符串//然后返回d函数c()()就把这个d函数进行调用就打印了d函数作用域 函数可以嵌套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,这里就好像执行了a函数还有b函数在执行完a函数返回b函数后这里就相当于b(),//之所以b函数能够打印y,是因为b的作用域变量就有xy通过console.dir可以看到而不是现在b函数//跟a函数在同一级就访问不了y了能访问到是因为就是因为存在闭包的概念。函数定义时它的作用域已经确定好了因此无论函数将来去了哪都能从它的作用域中找到当时那些变量别被概念忽悠了闭包就是指函数能够访问自己的作用域中变量 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遍历操作后并不会影响原有数组的数据 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 表示要留下的元素filter过滤后并不会改变原来数据arr还是1236 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字符串在进行转换过程中如果待处理的数据是JSON不支持的在转换的过程中就会报错。例如js对象中有一个属性值为undefined转为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 的类型未知必须根据不同类型做出相应的容错处理 }2. 运算符与表达式 - * / % ** (平方) - * / % ** --位运算、移位运算 ! ! ⭐️ || ! ⭐️?? ?. ⭐️... ⭐️解构赋值 ⭐️ 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};深层次的不能直接复制而是引用o1改了o2也会跟着改。 o1.name 李四 o2.name //打印结果还为张三 o1.address.city 上海 o2.address.city //打印结果为上海作用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 a,b,c ...arr //这种写法是错误的...只能用于参数传递时解构用在声明参数时 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);} }4. API 环境准备 1) 安装 nvm nvm 即 (node version manager)好处是方便切换 node.js 版本 安装注意事项 要卸载掉现有的 nodejs提示选择 nvm 和 nodejs 目录时一定要避免目录中出现空格选用【以管理员身份运行】cmd 程序来执行 nvm 命令首次运行前设置好国内镜像地址 nvm node_mirror http://npm.taobao.org/mirrors/node/ nvm npm_mirror https://npm.taobao.org/mirrors/npm/首先查看有哪些可用版本 nvm list available输出 | CURRENT | LTS | OLD STABLE | OLD UNSTABLE | |--------------|--------------|--------------|--------------| | 18.7.0 | 16.16.0 | 0.12.18 | 0.11.16 | | 18.6.0 | 16.15.1 | 0.12.17 | 0.11.15 | | 18.5.0 | 16.15.0 | 0.12.16 | 0.11.14 | | 18.4.0 | 16.14.2 | 0.12.15 | 0.11.13 | | 18.3.0 | 16.14.1 | 0.12.14 | 0.11.12 | | 18.2.0 | 16.14.0 | 0.12.13 | 0.11.11 | | 18.1.0 | 16.13.2 | 0.12.12 | 0.11.10 | | 18.0.0 | 16.13.1 | 0.12.11 | 0.11.9 | | 17.9.1 | 16.13.0 | 0.12.10 | 0.11.8 | | 17.9.0 | 14.20.0 | 0.12.9 | 0.11.7 | | 17.8.0 | 14.19.3 | 0.12.8 | 0.11.6 | | 17.7.2 | 14.19.2 | 0.12.7 | 0.11.5 | | 17.7.1 | 14.19.1 | 0.12.6 | 0.11.4 | | 17.7.0 | 14.19.0 | 0.12.5 | 0.11.3 | | 17.6.0 | 14.18.3 | 0.12.4 | 0.11.2 | | 17.5.0 | 14.18.2 | 0.12.3 | 0.11.1 | | 17.4.0 | 14.18.1 | 0.12.2 | 0.11.0 | | 17.3.1 | 14.18.0 | 0.12.1 | 0.9.12 | | 17.3.0 | 14.17.6 | 0.12.0 | 0.9.11 | | 17.2.0 | 14.17.5 | 0.10.48 | 0.9.10 |建议安装 LTS长期支持版 nvm install 16.16.0 nvm install 14.20.0执行 nvm list 会列出已安装版本 切换到 16.16.0 nvm use 16.16.0切换到 14.20.0 nvm use 14.20.0安装后 nvm 自己的环境变量会自动添加但可能需要手工添加 nodejs 的 PATH 环境变量 2) 检查 npm npm 是 js 的包管理器就类似于 java 界的 maven要确保它使用的是国内镜像 检查镜像 npm get registry如果返回的不是 https://registry.npm.taobao.org/需要做如下设置 npm config set registry https://registry.npm.taobao.org/3) 搭建前端服务器 新建一个保存项目的 client 文件夹进入文件夹执行 npm install express --save-dev前端项目的运行也要类似于后端运行时所需的服务器即Tomcat前端需要的是express。–save-dev表示express只在开发过程中有效打包后并不会到打包后的文件中执行完毕后目录结构如下 修改 package.json 文件该文件相当于maven项目中的pom.xml 修改后才能使用import这种导包方式。 {type: module,devDependencies: {express: ^4.18.1} }node_modules用于存储所需依赖的js包 其中 devDependencies 是 npm install --save-dev 添加的 编写 main.js 代码 //需要先修改 package.json 文件 import express from express //调用后返回express服务器对象 const app express() //静态资源的映射目录为当前目录 app.use(express.static(./)) //监听端口为7070 app.listen(7070)在当前项目下新建一个index.html文件 打开终端执行 js 代码运行前端服务器 node main.js访问localhost:7070/index.html 前端案例 初步效果 架构 前端只有静态页面使用 Express 服务器后端使用 Tomcat 服务器通过 SpringBoot、MyBatis 等框架获取数据库数据 1) 查找元素 document.getElementById - 根据 id 值查找一个元素[document|元素].querySelector - 根据选择器查找第一个匹配元素[document|元素].querySelectorAll - 根据选择器查找所有匹配元素 例如有下面的 html 代码 divdiv classtitle学生列表/divdiv classtheaddiv classrow bolddiv classcol编号/divdiv classcol姓名/divdiv classcol性别/divdiv classcol年龄/div/div/divdiv classtbodydiv classrowdiv classcol1/divdiv classcol张三/divdiv classcol男/divdiv classcol18/div/div/div /div执行 document.querySelector(.title); // 找到 div classtitle学生列表/div执行 document.querySelector(.col); // 找到 div classcol编号/div执行 document.querySelectorAll(.col);/*找到的是一个集合div classcol编号/divdiv classcol姓名/divdiv classcol性别/divdiv classcol年龄/divdiv classcol1/divdiv classcol张三/divdiv classcol男/divdiv classcol18/div */执行 const thead document.querySelector(.thead);// 只在 thead 元素范围内找 thead.querySelectorAll(.col);/*找到的是一个集合div classcol编号/divdiv classcol姓名/divdiv classcol性别/divdiv classcol年龄/div */根据 id 属性查找既可以用 document.getElementById(id值)也可以用 document.querySelector(#id值)2) 修改元素内容 元素.innerHTML元素.textContent 例如 document.querySelector(.title).innerHTML 侠客列表效果 innerHTML 会解析内容中的标签例如 textContext 不会解析内容中的标签 给 innerHTML 或 textContent 赋值空串可以实现清空标签内容的效果 3) 利用模板 divdiv classtitle学生列表/divdiv classtheaddiv classrow bolddiv classcol编号/divdiv classcol姓名/divdiv classcol性别/divdiv classcol年龄/div/div/divdiv classtbody/div /divtemplate idtpdiv classrowdiv classcolxx/divdiv classcolxx/divdiv classcolxx/divdiv classcolxx/div/div /templatescript// 将来这些数据从 java 端返回let array [{ id: 1, name: 张三, sex: 男, age: 18 },{ id: 2, name: 李四, sex: 女, age: 17 }];const tp document.getElementById(tp);const row tp.content;const [c1,c2,c3,c4] row.querySelectorAll(.col);const tbody document.querySelector(.tbody);for(const {id,name,sex,age} of array) {c1.textContent id;c2.textContent name;c3.textContent sex;c4.textContent age;// 复制元素const newRow document.importNode(row, true);// 建立父子关系左边父右边子tbody.appendChild(newRow);} /script4) Fetch API Fetch API 可以用来获取远程数据它有两种方式接收结果同步方式与异步方式 格式 fetch(url, options) // 返回 Promise同步方式 const 结果 await Promise // 后续代码await 关键字必须在一个标记了 async 的 function 内来使用后续代码不会在结果返回前执行 异步方式 Promise.then(结果 { ... }) // 后续代码 后续代码不必等待结果返回就可以执行 例 在 express 服务器上有 students.json 文件 [{ id: 1, name: 张三, sex: 男, age: 18 },{ id: 2, name: 李四, sex: 女, age: 17 } ]现在用 fetch api 获取这些数据并展示 同步方式 scriptasync function findStudents() {try {// 获取响应对象const resp await fetch(students.json)// 获取响应体, 按json格式转换为js数组const array await resp.json();// 显示数据const tp document.getElementById(tp);const row tp.content;const [c1,c2,c3,c4] row.querySelectorAll(.col);const tbody document.querySelector(.tbody);for(const {id,name,sex,age} of array) {c1.textContent id;c2.textContent name;c3.textContent sex;c4.textContent age;// 复制元素const newRow document.importNode(row, true);// 建立父子关系tbody.appendChild(newRow);}} catch (e) {console.log(e);}}findStudents() /scriptfetch(‘students.json’) 内部会发送请求但响应结果不能立刻返回因此 await 就是等待响应结果返回其中 resp.json() 也不是立刻能返回结果它返回的也是 Promise 对象也要配合 await 取结果 异步方式 scriptfetch(students.json).then( resp resp.json() ).then( array {// 显示数据const tp document.getElementById(tp);const row tp.content;const [c1,c2,c3,c4] row.querySelectorAll(.col);const tbody document.querySelector(.tbody);for(const {id,name,sex,age} of array) {c1.textContent id;c2.textContent name;c3.textContent sex;c4.textContent age;// 复制元素const newRow document.importNode(row, true);// 建立父子关系tbody.appendChild(newRow);}}).catch( e console.log(e) )/script第一个 then 是在响应返回后才会调用它里面的箭头函数箭头函数参数即 resp 响应对象第二个 then 是在 json 解析完成后才会调用它里面的箭头函数箭头函数参数即解析结果本例是 array 数组上一个 then 返回的是 Promise 对象时才能链式调用下一个 then 跨域问题 只要协议、主机、端口之一不同就不同源例如 http://localhost:7070/a 和 https://localhost:7070/b 就不同源 同源检查是浏览器的行为而且只针对 fetch、xhr 请求 如果是其它客户端例如 java http clientpostman它们是不做同源检查的通过表单提交、浏览器直接输入 url 地址这些方式发送的请求也不会做同源检查 更多相关知识请参考 跨源资源共享CORS - HTTP | MDN (mozilla.org) 请求响应头解决 fetch 请求跨域会携带一个 Origin 头代表【发请求的资源源自何处】目标通过它就能辨别是否发生跨域 我们的例子中student.html 发送 fetch 请求告诉 tomcat我源自 localhost:7070 目标资源通过返回 Access-Control-Allow-Origin 头告诉浏览器【允许哪些源使用此响应】 我们的例子中tomcat 返回 fetch 响应告诉浏览器这个响应允许源自 localhost:7070 的资源使用 代理解决 npm install http-proxy-middleware --save-dev在 express 服务器启动代码中加入 import {createProxyMiddleware} from http-proxy-middleware// ...app.use(/api, createProxyMiddleware({ target: http://localhost:8080, changeOrigin: true }));fetch 代码改为 const resp await fetch(http://localhost:7070/api/students)或 const resp await fetch(/api/students)5) 模块化 单个导出 const、let、function 在JS文件中写以下代码 export const a 10; export let b 20; export function c() {console.log(c); }一齐导出 const a 10; let b 20; function c() {console.log(c) }export {a,b,c}导出 default只能有一个 export const a 10; export let b 20; export function c() {console.log(c) }export default b;import 语法 script typemoduleimport 语句 /scriptimport 需要遵循同源策略 整个导入 import * as module from /1.js console.log(module.a) // 输出10 console.log(module.b) // 输出20 module.c() // 输出c单个导入 import {a,c} from /1.js console.log(a) // 输出10 c() // 输出c导入默认 import x from /1.js console.log(x) // 输出20
http://wiki.neutronadmin.com/news/308957/

相关文章:

  • 山东聊城网站设计python语言程序设计基础
  • 行业网站网址wordpress主题大前端dux去授权
  • 纪实摄影网站推荐wordpress阅读全文插件
  • 自己建网站做外贸公司经营范围
  • 怎么做点击图片跳转网站前几年做那个网站致富
  • 国外金融网站设计欣赏wordpress 分享至微信
  • 织梦建设网站需要什么软件软件工程师的工作内容
  • 产品网站免费模板外贸网站都有哪些内容
  • 潮安区建设局网站做门窗接活的网站
  • 兴文移动网站建设最好看的WordPress 音乐播放器
  • 太原网站优化方案沈阳做网站优秀公司
  • 设计师国外网站广西水利工程建设管理网站
  • 三亚住房和城乡建设厅网站重复打开同一个网站怎么做
  • 设计好的商城网站建设网络公司做网站小语种翻译多少钱
  • 网站项目分析怎么做 方法wordpress扫码收款
  • 音乐网站的音乐怎么做珠海网站制作专业
  • 揭阳有哪家网站制作公司wordpress小工具滑至顶部
  • 湖北海厦建设有限公司网站wordpress的文章title在哪里
  • 长沙网站制作的亚马逊跨境电商平台官网
  • 网络公司怎样推广网站摄影网站模板下载
  • 网站开发语言 微信接口单位如何建设网站
  • 金华企业网站建站模板湘潭网站建设 x磐石网络
  • 做网站的费用怎么录分录网站添加百度地图导航
  • 网站建设制作浩森宇特嘉兴地区有人做网站吗
  • 可以免费做3dLOGO的网站网站设计公司 宁波
  • 怎么怎么做网站墙纸 html 网站模板
  • 珠海网站建设成功案例自助建站系统php
  • 做网站公司深圳微信如何链接wordpress
  • 百度如何推广网站网站跳出率一般多少
  • 洛阳 网站建设公司哪家好seo网络排名优化哪家好