Java25:前端工程

Java25:前端工程 一.ES6 javascript的一次重大更新1. let 和const 关键字let和 var的区别1let 不能重复声明2let 有块级作用域非函数的话括号遇见let会有块级作用域也就只能在花括号里访问了3let不会预解析进行变量提升先定义后使用4let 定义的全局变量不会作为window的属性5let在es6中推荐优先使用const 定义 常量 相当于java的final关键字2.解构表达式es6的解构赋值是一种方便的语法可以快速将数组或对象中的值拆分并赋值给变量。解构赋值的语法使用花括号{}表示对象方括号[] 表示数组通过解构赋值函数更方便进行参数接受等arr [11,22,33,44]//使用解构表达式获取数组的元素let [a,b,c,d,e10]arrconsole.log(a,b,c,d,e)let person {name:zhangsan,age:20}//使用解构表达式取出对象的属性let {age,name}personconsole.log(age,name)3. 箭头函数语法类似java中的lambda表达式 let fun1function(){}//普通函数定义let fun2(){}//箭头函数定义let fun3(x){return x1}//如果参数为空或者大于一个小括号不能省略let fun4x {return x1} //如果参数为一个小括号可以省略let fun5x x1 //如果函数体就一行代码花括号和return也可以省略//this 关键字在箭头函数中表示外层的上一下文对象let person {name:zhangsan,age:20,showname:function(){console.log(this)//person 对象console.log(this.name)},showname2:(){console.log(this)//windows对象console.log(this.name)}}person.showname()person.showname2()4. rest 和spreadrest相当于可变形参spread是把可变数组的每个值作为实参分别传入//rest ...arr1 ,表示可变形参let fun1(a,b,c,...arr1){console.log(a,b,c)console.log(arr1)}fun1(1,2,3,4,5,6)let arr1[1,2,3]let fun2(a,b,c){console.log(a,b,c)}//把arr1都传给第一个参数后面两个都为undefinedfun2(arr1)//spread ,把数组的元素分别传给每个对象fun2(...arr1)//合并数组let a1[1,2,3]let a2[4,5,6]let a3[7,8,9]let a4[...a1,...a2,...a3]console.log(a4)//合并对象let p1{ name:zhangsan }let p2{ age:10 }let p3{ gender:boy }let p4{...p1,...p2,...p3}console.log(p4)5类 对象继承class Person{//属性name;age;//geter setterget name(){return this.name}set name(name){this.namename}//实例方法eat(food){console.log(${this.age}岁的${this.name}正在吃${food})}//静态方法static hello(){console.log(你是一个好人)}//构造器constructor(name,age){this.namenamethis.ageage}}let per new Person()per.namezhangsanper.age10per.eat(火锅)Person.hello()let per2 new Person(xiaoming,15)per2.eat(火锅)//继承class Student extends Person{scoreconstructor(name,age,score){super(name,age)this.scorescore}stduy(){console.log(${this.age}岁的${this.name}好好学习考了 ${this.score}分)}}let stu new Student(王二,10,99);stu.stduy()6.浅拷贝与深拷贝//浅拷贝let arr1[1,2,3,4]let arr2arr1arr1[0]100console.log(arr2)let per1{name:zhangsan}let per2per1per1.namezhangwuconsole.log(per2.name)//深拷贝let arr11[1,2,3,4]let arr22[...arr11]arr11[0]100console.log(arr22)let per11{name:zhangsan}//let per22{...per11}let per22 JSON.parse(JSON.stringify(per11))per11.namezhangwuconsole.log(per22.name)二nodejsnpm1.nodejs简介nodejs 是一个基于chrome v8引擎的JavaScript运行时环境可以使JavaScript运行在服务器端下载地址https://nodejs.org/en运行js文件方法在windows名字行中 输入 node XX.js查看nodejs版本在windows名字行中 输入 node -v2.npm简介:npm 全称 Node Package Manager是Node.js包下载和管理工具相当与后端的Mavennpm的安装和配置安装node自动安装npm包管理工具查看 下载配置包的配置依赖在命令行输入 npm config get registry外国的源地址 https://registry.npmjs.org/阿里的源地址https://registry.npmmirror.com配置 下载配置包的配置依赖npm config set registry https://registry。npmmirror.com查看全局仓库地址在命令行输入npm config get prefix设置全局仓库地址在命令行输入npm config set prefix D:\java\nodeglobalmodule下载或升级具体的工具包(-g 表示下载到全局仓库)npm 在命令行输入npm install -g vue33. npm常见命令1.项目初始化npm init执行命令后npm会引导你在命令行回答一些问题并最终生成一个package.json文件package.json文件会包含基本信息类似maven的pom.xmlnpm init -y执行命令后默认生成一个package.json文件不用挨个填写2.安装依赖查看所有依赖https:www.npmjs.com安装指定包名和版本号npm install 包名版本号安装最新包名npm install 包名在中央仓库安装npm install -g 包名安装 package.json 中所有记录的依赖npm install 或者 npm i3.升级依赖npm update 包名4.卸载依赖npm uninstall 包名5.查看依赖npm list三 .vue框架1.简介是一款用于构建用户界面的javaScript框架它基于标准HTML,CSS,JavaScript构建并提供了一套声明式的组件化的编程模型帮助你高效的开发用户界面。2.Vite工具作用构建标准的前端工程项目步骤1.使用命令行创建工程npm create vite根据提示依次输入工程名选择vueJavaScript2.安装项目所需的依赖cd 进入刚刚创建的项目目录npm install 命令安装基础依赖3.启动项目查看项目所属的package.json,查看scripts执行命令 npm run dev出现网络地址后点击出现viteVue的界面表示工程创建成功3.模板语法1.插值表达式插值表达式最基本的数据绑定形式是文本插值语法双大括号{{}}插值表达式是将数据渲染到元素的指定位置的手段之一插值表达式不绝对依赖标签其位置相对自由插值表达式中支持javascript的运算表达式插值表达式中也支持函数的调用实例//在script标签中定义变量,函数数组script setuplet v1hello vue3let v2 (){return nihao and vue3}let v3font colorrednihao/fontlet v4{url:http://www.atguigu.com,title:猫咪}let age20let bee蜜 蜂let carts[{name:可乐,price:3,number:5},{name:薯片,price:5,number:8}]function compute(){let count0for(let index in carts){count carts[index].price*carts[index].number}return count}let imhttp://www.atguigu.com/images/index_new/logo.pngfunction f1(){alert(菜鸡)}/script//在template标签中使用插值表达式调用变量函数数组template!--插值表达式的格式 {{变量/函数/对象/表达式}} --h1{{v1}}/h1!--插值表达式的格式可以放到标签里也可以单独使用 --{{v2()}}{{age18 ?是:否}}br{{carts[0].price*carts[0].numbercarts[1].price*carts[1].number}}{{compute()}}{{bee.split( ).reverse().join(-)}}brbrbrbrbr/template2.文本渲染使用v-text 和 v-html命令给文本赋值v-***这种写法的方式使用的是vue的命令v-*** 命令必须依赖元素并且要写在元素的开始标签中v-*** 指令支持ES6中的字符串模板v-text可以将数据渲染成双标签中间的文本但是不识别html元素结构的文本v-html 可以将数据渲染成双标签中间的文本识别html元素结构的文本实例templatebuttion id b1 v-textv1/buttionbrbuttion id b2 v-textv2()/buttionbrbuttion id b3v-textcompute()/buttionbrbuttion id b4v-textage18?y:n/buttionbrbuttion id b5v-textv3/buttionbrbuttion id b6 v-htmlv3/buttionbrbr/template3.Attribute属性渲染想要渲染一个元素的attribute,应该使用v-bind指令由于插值表达式不能值接放在标签的属性中所有要渲染的元素的属性就应该用v-bind指令v-bind可以用于渲染任何元素的属性语法为 v-bind:属性名数据名可以简写为 :属性名数据名实例templateimg v-bind:srcimbrimg :srcimbr/template4.事件渲染命令使用 v-on 来监听DOM事件并在事件触发时执行对应的Vue的js代码用法v-onclickhandler或简写为clickhandlervue中的事件名原生事件名去掉on前缀如onClick--clickhandler的值可以是方法事件处理器也可以是内联事件处理器绑定事件时可以通过一些绑定的修饰符常见的事件修饰符如下.once :致触发一次事件.prevent :阻止默认事件实例template!-- 函数的事件绑定 --button v-on:clickfun1()按钮1/buttonbutton v-on:clickfun2()/buttonbrbutton clickfun2()/buttonbr!-- 函数的内联绑定 --button v-on:clickcounterc/button!-- 事件的修饰符 .once 只执行一次.prevent 阻止组件的默认行为 --button v-on:click.oncefun2()/button{{counter}}a hrefhttp://baidu.com v-on:clickfun3()百度/abra hrefhttp://baidu.com v-on:click.preventfun4()百度2/a/template5.响应式数据的处理方式让一个普通的数据抓换为响应使数据的两种方式1.ref 函数 更适合单个变量在script标签中操作ref响应式数据要通过.value在template中操作ref响应式数据则无需通过.value2.reactive 函数 更适合对象在script template 操作reactive 响应式数据都直接使用对象名.属性名的方式即可实例script setupimport{ref,reactive}from vuelet counterref(1)function fun1(){counter.value}let personreactive({name:tom,age:10})function fun2(){person.age}/scripttemplatebutton clickfun1()/button{{counter}}button clickfun2()r/button{{person.age}}/template6.条件渲染v-if 条件渲染v-if表达式 只会在指令的表达式返回真值时才会被渲染也可以使用v-else 为v-if 添加一个 else区块一个 v-else 元素必须跟在一个v-if元素后面否则它将不会被识别v-show条件渲染用法基本和v-if 一致不同之处是 会在DOM渲染中保留该元素v-show仅切换了该元素上名为display的css属性值举列script setupimport {ref} from vuelet flagref(true)/scripttemplateh1 idha v-ifflag vue if test!/h1h1 idhb v-elseoh ,no body/h1h1 idhc v-showflag vue show test!/h1button clickflag!flagtoggle/button/template7. 列表渲染v-for 列表渲染v-for 指令的值需使用 item in items形式的特殊语法其中items是迭代项的别名在v-for 块中可以完整的访问父作用域的属性和变量v-for 也支持使用可选的第二个参数表示当前项的位置索引script setupimport {reactive} from vuelet foodsreactive([烤肉,火锅,烧烤])let cartsreactive([{name:可乐,price:3,number:10},{name:薯片,price:5,number:6},{name:鸡翅,price:8,number:5}])// 计算 购物车的总金额function compute(){let counter0;for(let index in carts){countercarts[index].price*carts[index].number}return counter}//删除指定元素function removeIndex(index){//从指定索引删除几个元素carts.splice(index,1)}//一键删除function removeAll(){carts.splice(0,carts.length)}/scripttemplateulli v-for item in foods v-textitem/li/ulhrtable border1pxtheadtrtd序号/tdtd商品/tdtd价格/tdtd数量/tdtd小计/tdtd操作/td/tr/theadtbodytr v-for(cart,index) in cartstd v-textindex1/tdtd v-textcart.name/tdtd v-textcart.price/tdtd v-textcart.number/tdtd v-textcart.number*cart.price/tdtdbutton clickremoveIndex(index)删除/button/td/tr/tbody/table购物车总金额为{{compute()}}元button clickremoveAll()一键清空购物车/button/template8. 双向绑定单项绑定 v-bind 响应式数据发送变化时更新dom树 用户的操作如果造成页面内容的改变不会影响响应式数据双向绑定 v-model 页面上的数据由于用户的操作造成了改变也会同步修改对应的响应式数据双向绑定一般都用于表单标签实例script setupimport {ref,reactive} from vuelet userreactive({name:,pwd:,intro:,pro:})let hobiesref([])function clearform(){user.nameuser.pwduser.introuser.prohobies.value.splice(0,hobies.value.length)}/scripttemplate用户名: input typetext v-modeluser.namebr密码 input typepassword v-modeluser.pwdbr爱好input typecheckbox v-modelhobies value1 唱input typecheckbox v-modelhobies value2 跳input typecheckbox v-modelhobies value3 rapbr简介:textarea v-modeluser.intro/textareabr籍贯select v-modeluser.probroption value1京/optionoption value2津/optionoption value3冀/option/selectbr{{user}}br{{hobies}}brbutton clickclearform()一键清空/button/template4.路由的使用定义路由就是根据不同的URl地址展示不同的内容或页面案例 步骤1.创建项目和导入路由依赖npm create vite 创建项目npm install 安装项目依赖npm install vue-router 安装路由的依赖2.准备页面和组件在 components目录下创建子组件3.在src 路径下创建路由文件目录src/routers/router.js//导入创建路由需要的函数import{createRouter,createWebHashHistory} from vue-router//导入对应的组件import Home from ../components/Home.vueimport List from ../components/List.vueimport ShowDetail from ../components/ShowDetail.vueimport ShowDetail2 from ../components/ShowDetail2.vue//创建路由对象const routercreateRouter({history:createWebHashHistory(),//定义路径和组件的对应关系routes:[{path:/home,component:Home},{path:/list,component:List}]})//暴漏路由对象export default router4.在main.js 引入路由import { createApp } from vueimport App from ./App.vue//在整个app 应用路由import router from ./routers/router.jsconst appcreateApp(App)app.use(router)app.mount(#app)5.配置app.vuescript setupimport{useRouter} from vue-routerlet routeruseRouter()function getMyPath(){router.push(/list)}/scripttemplatedivapp之前的内容br!-- 声明式路由--router-link to/listlist/router-linkbrrouter-link to/homehome/router-linkbrrouter-link to/showdetailshowdetail/router-linkbr!-- 编程式路由--button clickgetMyPath()按钮/button!-- 替换并展示组件内容--router-view/router-view6.路由传参分为路径参数和键值对参数案例1. router.js 的配置{ //键值对路径配置path:/showdetail2,component:ShowDetail2},{ //路径配置path:/showdetail/:id/:language,component:ShowDetail}2.组件showDetail.vue 路径组件内容script setupimport {ref} from vueimport {onUpdated} from vueimport{useRoute} from vue-routerconst routeuseRoute()let param_idref(0)let param_languageref()param_id.valueroute.params.idparam_language.valueroute.params.language//切换更新界面值onUpdated((){//route.params 获取路径参数值param_id.valueroute.params.idparam_language.valueroute.params.language})/scripttemplatedivh1{{param_id}}{{param_language}} 是世界上最好的编程语言/h1/div/templatestyle scoped/styleshowDetail2.vue 键值对组件内容script setupimport {ref} from vueimport{useRoute} from vue-routerlet routeuseRoute()let param_idref(0)let param_languageref()//获取键值对参数值param_id.valueroute.query.idparam_language.valueroute.query.language/scripttemplatedivh1{{param_id}}{{param_language}} 是世界上最好的编程语言/h1/div/templatestyle scoped/style3.配置app.vuescript setupimport{useRouter} from vue-routerlet routeruseRouter()function showdetail(id,language){//router.push(/showdetail/${id}/${language})router.push({path:/showdetail/${id}/${language}})}function showdetail2(id,language){//router.push(/showdetail2?id${id}language${language})router.push({path:/showdetail/${id}/${language}})}/scripttemplatedivrouter-link to/showdetail/1/java声明式路径传参/router-linkbrbutton clickshowdetail(2,php)编程式路径传参/buttonhrrouter-link to/showdetail2?id1languagejava声明式键值对传参/router-linkbrrouter-link v-bind:to{path:/showdetail2,query:{id:2,language:php}}声明式键值对传参2/router-linkbrbutton clickshowdetail2(3,python)编程式键值对传参/buttonrouter-view/router-view/div/templatestyle scoped/style5.路由守卫1简介: 在vue3中路由守卫是用于在路由切换间进行一些特定任务的回调函数路由守卫可以用于许多任务例如验证用户是否已登录在路由切换前提供确认提示请求数据等2.分类全局前置守卫:在路由切换前被调用,可以用于验证用户是否已登录,中断导航/请求数据等全局后置守卫:在路由切换之后被调用,可以用于处理数据,操作DOM,记录日志等守卫代码的位置:在router.js中3:举列://路由前置守卫router.beforeEach((to,from,next){//to 是目标包装对象,.path属性可以获取地址// from 是来源地包装对象 .path属性可以获取地址//next 是方法,不调用默认拦截, next() 放行 ,直接到达目标组件//next(/地址)可以转发到其他地址,到达目标组件会再次经过前置路由守卫console.log(beforeEach)console.log(to.path)console.log(from.path)next()})//路由后置守卫router.afterEach((to,from){//to 是目标包装对象,.path属性可以获取地址// from 是来源地包装对象 .path属性可以获取地址console.log(afterEach)console.log(to.path)console.log(from.path)})6.promise前端中的异步编程技术类似java中的多线程线程结果回调promise 简单的来说是一个容器里面保存着某个未来才会结束的事件通常是一个异步操作的结果从语法上说promise是一个对象从它可以获取异步操作的消息。promise提供统一的API各种异步操作都可以用同样的方法进行处理promise对象有以下两个特点1.promise 对象代表一个异步操作有三种状态pending进行中,Resolved(已完成)和reject已失败只有异步操作的结果可以决定当前是哪一种状态任何其他操作都无法改变这个状态2.一旦状态改变就不会在变任何时候都可以得到这个结果promise对象的状态改变只有两种可能从pending变成Resovled 或者从pending 变成 reject。只有这两种情况发生状态就凝固了。不会在变了会一直保持这个结果。实例新建promise.html,在浏览器执行script //resolve函数在回调函数中如果调用resolve方法promise会由pending转换为resolved//reject 函数在回调函数中如果调用reject方法promise 会由pending转换为rejectlet promise new Promise(function(resolve,reject){console.log(function code)//resolve(haha)// reject(no way)throw new Error(error message)})//promise 转换为resolved会执行的函数promise.then(function(values){console.log(sucessvalues)//promise 转换为rejecd会执行的函数}).catch(function(values){ console.log(failvalues)})console.log(code1)console.log(code2)/script7 关键字 async 和 awaitasync 帮助我们使用简洁的语法获得一个prmoise对象let promise new Promise(function(){})async function aaa(){}1.async 用于标识函数的async 函数返回的结果就是一个 promise2.方法如果正常return 结果promise的状态就是resolvedreturn 后的结果就是成功状态的返回值3.方法中出现了异常则返回的promise 就是一个失败的状态4.async 函数返回的结果如果是一个promise 则状态内部的promise 决定await await 帮助我们获取promise成功状态的返回值的关键字1.await右边如果是一个普通值则直接返回该值如果右面是promise返回promise成功状态的结果let res await 张三let res await Promise.resolve张三res张三2.await 右边如果是一个失败状态的promise 那么 await会直接抛异常3.await 关键字必须在async 修饰的函数中使用async函数中可以没有await4.await 后面的代码会等待await 执行完毕继续运行8.axiosAxios 是一个基于promise 网络请求库作用于node.js和浏览器中。在服务端它使用原生node.js http 模块而在客户端则使用XMLHttpRequests,有如下特性从浏览器创建XMLhttpRequests从 node.js创建http请求支持PRmoise api拦截请求和响应转换请求和响应数据取消请求自动转换JSON数据客户端支持防御XSRF案例请求后台获取随机土味情话script setupimport axios from axiosimport {ref ,reactive} from vuelet coderef()let contentref()let messagereactive({id:,text:})function getLoveMessage(){//axios({})请求三要素 1.请求的url 2请求的方式 3.请求的参数let promiseaxios({method:post,//url:https://api.uomg.com/api/rand.qinghua?fomatjson,url:https://api.uomg.com/api/rand.qinghua,data:{//如果请求方式是get则需要通过params 进行发送//如果请求方式post并使用data 数据会以json形式放入请求体},params:{// 都是以键值对方式将数据放入url后format:json,username:zhangsan}})promise.then(function(response){//response 响应结果对象//data 响应结果数据//status响应状态码console.log(response)code.value response.data.codecontent.valueresponse.data.contentmessage.idresponse.data.codemessage.textresponse.data.contentObject.as}).catch(function(Error){console.log(Error)})}/scripttemplatedivh1 v-textcontent/h1h2 v-textmessage.text/h2button clickgetLoveMessage()变/button/div/templatestyle scoped/styleaxios的get和post方法axios.get(url)axios.get(url,{请求的其他信息})axios.get(url,{params:{键值对信息}header:{设置一些特殊的请求头}})axios.post(url,{放入请求体的json串},{params:{键值对信息}})案例请求后台获取随机土味情话改进版script setupimport axios from axiosimport {reactive} from vuelet messagereactive({mid:,mcontent:})function getWord(){//return axios.get(https://api.uomg.com/api/rand.qinghua?fomatjson)//return axios.get(https://api.uomg.com/api/rand.qinghua,{params:{fomat:json}})return axios.post(https://api.uomg.com/api/rand.qinghua,{username:zhangsan,password:123456},{params:{fomat:json}})}async function getLoveMessage(){let resultawait getWord()console.log(result)console.log(result.data)//Object.assgin(result.data,message)message.midresult.data.codemessage.mcontentresult.data.content}/scripttemplatedivh2 v-textmessage.mcontent/h2button clickgetLoveMessage()变/button/div/templatestyle scoped/styleanxios拦截器如果想在axios 发送请求之前或者是响应回来在执行then方法之前做一些额外的工作可以通过拦截器完成案例拦截器的使用1在src目录下新建axios.js 文件import axios from axiosconst instanceaxios.create({})// 请求拦截器instance.interceptors.request.use(function(config){console.log(请求前拦截器)config.headers.Acceptapplication/jsonreturn config},function(error){console.log(请求拦截器异常方法)return Promise.reject(something goes wrong)})//响应拦截器instance.interceptors.response.use(function(response){//返回状态码为200执行的方法console.log(response sucess)console.log(response)// 一定要返回responsereturn response},function(error){console.log(response fail)console.log(error)// 一定要返回promisereturn Promise.reject(somehting goes wrong)})export default instance2app.vue 文件script setupimport instance from ./axios.jsimport {reactive} from vuelet messagereactive({mid:,mcontent:})function getWord(){return instance.post(https://api.uomg.com/api11/rand.qinghua,{username:zhangsan,password:123456},{params:{fomat:json}})}async function getLoveMessage(){let resultawait getWord()console.log(result)console.log(result.data)//Object.assgin(result.data,message)message.midresult.data.codemessage.mcontentresult.data.content}/scripttemplatedivh2 v-textmessage.mcontent/h2button clickgetLoveMessage()变/button/div/templatestyle scoped/style9.pinia通过pinia状态管理定义共享数据当我们有多个组件共享一个共同的状态数据源时多个视图可能都依赖于同一份状态。来自不同视图的交互也可能需要更改同一份状态pinia 就是实现了上述需求的状态管理库由vue核心团队维护实例实现数据在两个组件共享1)新建store.jsimport {defineStore} from piniaexport const piniaPersondefineStore({id:pinia,state:(){return {username:zhangsan,age:10,hobbies:[唱歌,跳舞,打篮球]}},getters:{getAge(){return this.age},getHobbiesCount(){return this.hobbies.length}},actions:{doubleAge(){return this.agethis.age*2}}})2)两个组件Operate 组件script setupimport {piniaPerson} from ../store/store.jslet personpiniaPerson()/scripttemplatedivh1operate/h1用户名 input typetext v-modelperson.usernamebr年龄 input typetext v-modelperson.agebr爱好吃饭input typecheckbox value吃饭 v-modelperson.hobbies睡觉input typecheckbox value睡觉 v-modelperson.hobbies打篮球input typecheckbox value打篮球 v-modelperson.hobbies唱歌input typecheckbox value唱歌 v-modelperson.hobbies跳舞input typecheckbox value跳舞 v-modelperson.hobbiesbrbutton clickperson.$reset()重置/buttonbutton clickperson.doubleAge()年龄加倍/buttonbutton clickperson.$patch({username:奥特曼,age:5000,hobbies:[打怪兽,放大招]})变身/buttonhr{{person }}/div/templatestyle scoped/stylelist组件script setupimport {piniaPerson} from ../store/store.jslet person piniaPerson()/scripttemplatediv用户名{{person.username }}br年龄{{person.age }}br爱好ulli v-for(hobby,index) in person.hobbies :keyindexv-texthobby/li/ul/div/templatestyle scoped/style3路由配置router.jsimport{createRouter,createWebHashHistory} from vue-routerimport Operate from ../components/Operate.vueimport List from ../components/List.vueconst router createRouter({history:createWebHashHistory(),routes:[{ path:/operate,components:{default:Operate,list:List}},{ path:/list,component:List},{ path:/,component:Operate}]})export default router4)main.js 使用pinia对象import { createApp } from vueimport App from ./App.vueimport router from ./router/router.jsimport { createPinia } from pinialet piniacreatePinia()let app createApp(App)app.use(router)app.use(pinia)app.mount(#app)