vue,狂神,狂神和飞哥,前端一直在抄袭后端
Vue.js (vuejs.org)
Bootstrap可视化布局系统 (bootcss.com)
MyBatis入门学习-KuangStudy-文章
一 前端体系
- 此课程的重点
- 前端的话,页面我不会再给大家多讲了。重点难就难在,这些框架怎么使用,比如说前端化工程。
- java全栈工程师:
- 后台开发:主打
- 前端:html、css、js、jquery、bootstrap、layui、vue、react......
- 运维:项目发布;服务器如何运行一个项目?
- 前端组成,3要素
- html:结构层
- css:表现层。如改颜色、加边框、定位......
- CSS预处理器
- 业务:css不是编程语言,而是标记语言。语法不够强大,没有变量和合理的样式复用机制。
- 需求:
- 解决上面的问题。
- 作用:提供 CSS 缺失的样式层复用机制、减少冗余代码,提高样式代码的可维护性和开发效率。
- 思想(路):CSS 预处理器定义了一种新的语言,这种专门的编程语言,为 CSS 增加了一些编程的特性,将 CSS 作为目标生成文件(即程序本身并不是css言语写的,但这个程序运行的结果,它会产生一个css文件,即用程序的方式去编。类似于java程序编译打包完成,会产生一个.jar包一样。),然后开发者就只要使用这种语言进行 CSS 的编码工作。
转化成通俗易 懂的话来说就是“用一种专门的编程语言,进行 Web 页面样式设计,再通过(前端)编译器转化为正常的 CSS 文件,以供项目使用”。
- 流(原):如淘宝每年都会有年中618、双11、双12是吧,而这3个购物节使用的css样式肯定不一样是吧。那怎么办呢?每到一个购物节,阿里的那些开发人员,肯定不会直接把css写死在页面中,这样写死地改来改去会非常消耗人力和时间,很麻烦。那到底怎么办呢?他们会想一些办法,跟编程一样,写一个程序让程序自动输出css。每到一个购物节,就去改程序,自动输出新的css样式即可。动态输出css(如定时输出),这就是所谓的css预处理器。
- 常用的css预处理器有哪些:
- SASS:基于 Ruby,通过服务端处理,功能强大。解析效率高。需要学习 Ruby 语言,上手难度高于 LESS。
- LESS:基于 NodeJS,通过客户端处理,使用简单。功能比 SASS 简单,解析效率也低于 SASS,但在实际开发中足够了,所以如果我们后台人员如果需要的话,建议使用 LESS。
- 总结:几乎现在专业的前端都在用LESS写,如果做为一个前端还在用css写,那你效率会很低。
- CSS预处理器
- javascript:行为层
- Native:最早,是原生JS开发。
- 原生 JS 开发,也就是让我们按照 ECMAScript(ES)标准的开发的。
- 目前的情况:最高版本是es9,最流行的是es6,但很多浏览器还停留在es5,而且对于大多数浏览器厂商的最高版本也只是部分支持es6。对于不支持es6的浏览器(低版本)来说怎么办呢?开发时可以使用es6规范去开发,但需要用webpack打包工具把es6的代码降级成为es5,如let转var。
- TypeScript微软的标准
- 业务:javascript的缺陷
- 需求:解决这些缺陷
- 流(原):很神奇,微软的TypeScript编写的程序,运行的结果是变成一堆javascript代码。和上面的less一样,你用less编写的程序,运行的结果是不是生成css了。
- Native:最早,是原生JS开发。
- 常用的javascript构架:
- jquery:就是一个类库。
- Angular:mvvm
- 如何理解:“将后台的 MVC 模式搬到了前端并增加了模块化开发的念”?
- mvc的3要素分别是,m(模型)、v(视图)、c(控制器)。
- 原来的前端:只有一个v(视图),即html + css + js。后面ajax出现了,使用ajax(Axios)以后,可以与后台进行通信、交互。而视图的数据(data,即m(模型))都是我们后端给它渲染过去的。
- Angular前端:在前端实现了mvc架构(模式),称为mvvm,其中m(模型)、v(视图)、vm(view model,即数据双向绑定)。
- 如何理解:“将后台的 MVC 模式搬到了前端并增加了模块化开发的念”?
- React:虚拟化dom
- 原来的dom操作:是通过js(如document.getElementByTag/getElementById等),对dom树进行CRUD,或者在获取dom对象以后对dom对象的文档、css进行一定的调整。
- 虚拟dom:最大的特点是它利用了内存,利用内存来缓存一些dom元素,并在内存中操作dom,有效地提高了前端的渲染率。 你们都听过,vuejs的“计算属性、计算属性缓存 vs 方法”这2个东西是吧。以前学计算属性的时候,老师是不是跟你们讲了虚拟dom。“计算属性“是vue的特色,是vue独有的。而“计算属性“这个特色是怎么来的?就是利用虚拟dom来的。
- Vue:mvvm + 虚拟化dom
- 渐进式:就是逐步实现新特性的意思,比如vuejs会慢慢去实现es6的规范、慢慢去实现模块化的规范、慢慢实现虚拟化dom、慢慢模块化、慢慢路由、慢慢状态管理等等。
- vue集成了Angular和React的优点,即说明了vue中也有mvvm、也有虚拟化dom。
- 后端学习它并不会觉得很难,因为它是模块化开发的。
- Axios
- 前端的通信框架,只做通信(soc原则),相当于ajax、jquery ajax。
- 前端流行的UI框架
- Ant-Design
- ElementUI:主要特点是桌面端支持较多
- iview:主要特点是移动端支持较多
- ice
- Bootstrap
- AmazeUI
- javascript构建工具
- babel:一般更多地是用于编译TypeScript。
- webpack:模块打包工具,一般会用它来打包咱们的前端程序。
- 总结:前端也在发展(css框架成百上千、javascript的框架也成面上千),但发展的很乱,但始终有一些是流行的、受到行业追捧的东西。
- 前端知识,6要素
- 逻辑
- 判断:判断一下这东西该不该展示
- 循环
- 事件
- 那我们刚才跟你说的那堆javascript代码(BOM、DOM操作),它是在干嘛?是不是叫做事件呀。事件的话那就非常多了,但总的来说就两类:浏览器事件(BOM)和标签事件(DOM)。BOM事件,说得难听一点,其实也就两个window事件、document(文档)事件。DOM事件常见的:增、删、遍历、修改节点元素内容。
- 那么前端所说的事件,有没有框架来做呀?有呀,比如jquery(库)封装了大量的事件、vuejs、React......
- 视图:应该怎么画才好看
- 前端所说的视图视图说白了就是:第1点:给用户看;第2点:刷新后台,就是做这两件事情而已。
- 前端所说的视图由谁来做?html、cs、js呀。
- 其实前端最难的是css,一个像素都不能错,不然不好看。
- 基于html、css衍生出很多我们熟知的前端视图框架:bootstrap、layui、Vue-Ui即vue相关的视图组件框架库(如飞冰ice.work、Element-Ui)......
- 网络通信
- xhr:原生javascript
- ajax:jquery封装
- axios框架:vuejs
- 页面跳转:
- 路由(转发):vue自己开发的组件:vue-router,来控制页面跳转的。
- 状态管理:
- 状态管理:就是vue会把所有的东西统一管理,这就是vuex来做的。
- 逻辑
- Vue概述
- 前端3大框架:vue、AngularJS、React.js。
- vue是一个渐进式的前端框架。
- Vue 的核心库只关注视图层,这句话什么意思?其中视图层,就是html、css、js做的东西吧。而网络通信,vue用管吗?不用。使用的是axios框架,去管网络通信的部分。页面跳转,vue用得着管吗?也不用。使用的是vuejs自己开发的组件vue-router,去管页面跳转的部分。状态管理,vue用得着管吗?那也不用。使用的是,vuex来做的。也就是说vue只关注视图层的意思是,vue只跟上面的这3个(html、css、js)打交道。
Vue只关注视图层,并遵守一个原则,叫做soc原则(Separation of concerns,关注点分离原则,关注点分离 - 中文维基百科【维基百科中文版网站】 (cljtscd.com))。也就是说,它会把它的关注点分得特别散,vue只管视图层。
- webpack
- 原理:最高版本是es9,最流行的是es6,但很多浏览器还停留在es5,而且对于大多数浏览器厂商的最高版本也只是部分支持es6。对于不支持es6的浏览器(低版本)来说怎么办呢?开发时可以使用es6规范去开发,但需要用webpack打包工具把es6的代码降级成为es5,如let转var。webpack把es6的代码打包成浏览器能够认识的代码。
我们后台有没有打包工具?有,maven就是我们后台的打包工具(构建、管理、打包工具),maven就是把java源代码打包成服务器能够认识的程序。
- 原理:最高版本是es9,最流行的是es6,但很多浏览器还停留在es5,而且对于大多数浏览器厂商的最高版本也只是部分支持es6。对于不支持es6的浏览器(低版本)来说怎么办呢?开发时可以使用es6规范去开发,但需要用webpack打包工具把es6的代码降级成为es5,如let转var。webpack把es6的代码打包成浏览器能够认识的代码。
二 前端:三端统一开发
- 混合开发(Hybrid App)
- 主要目的是实现一套代码三端统一(PC、Android:.apk、IOS:.ipa)并能够调用到设备底层硬件(如:传感器、GPS、摄像头等),打包方式主要有以下两种:
- 云打包:HBuild -> HBuildX ,DCloud出品;API Cloud
- 本地打包:Cordova(前身是 PhoneGap)
- 主要目的是实现一套代码三端统一(PC、Android:.apk、IOS:.ipa)并能够调用到设备底层硬件(如:传感器、GPS、摄像头等),打包方式主要有以下两种:
- 微信小程序
- 详见微信官网,这里就是介绍一个方便微信小程序UI开发的框架:WeUI。
三 后端技术:前端所需后端技术
- Express:NodeJS 框架
- Koa:Express 简化版
- NPM:项目综合管理工具,类似于 Maven。npm install(安装)其实就相当于java maven下载依赖包,且进行包管理。
- YARN:NPM 的替代方案,类似于 Maven 和 Gradle 的关系。
四 前后端分离的演变史
- 第1阶段,2005年之前(web 1.0):后端为主的 MVC 时代,如springmvc
- 流程
- 发起请求到前端控制器( DispatcherServlet )
- 前端控制器请求 HandlerMapping 查找 Handler ,可以根据 xml 配置、注解进行查找
- 处理器映射器 HandlerMapping 向前端控制器返回 Handler
- 前端控制器调用处理器适配器去执行 Handler
- 处理器适配器去执行 Handler
- Handler 执行完成给适配器返回 ModelAndView
- 处理器适配器向前端控制器返回 ModelAndView , ModelAndView 是 SpringMVC 框架的一个底层对象,包括 Model 和 View
- 前端控制器请求视图解析器去进行视图解析,根据逻辑视图名解析成真正的视图( JSP )
- 视图解析器向前端控制器返回 View
- 前端控制器进行视图渲染,视图渲染将模型数据(在 ModelAndView 对象中)填充到 request 域
- 前端控制器向用户响应结果
- 注:图里面的所有东西,只有一个controller是开发者需要做的而已。
- 缺点
- 前后端职责纠缠不清
- 流程
- 第2阶段:2005年(web 2.0):基于 AJAX 带来的 SPA 时代
- 第3阶段:now现在:大前端时代,即前端为主的 MV* 时代
- MV*
- MVC(同步通信为主):Model、View、Controller
- MVP(异步通信为主):Model、View、Presenter
- MVVM(异步通信为主):Model、View、ViewModel
- 1 ~ 1.8 ~ 3
- 分布式、微服务、大数据
- MV*
- 第4阶段:NodeJS 带来的全栈时代
- 如nodejs前后端都可以做了。
- 但nodejs永远都不可能干掉java,因为js语言有它天生的弊端。
五 MVVM模式
1 MVVM模式的组成部分
- 从上图可知道MVVM的组成部分:
- V - View
- HTML
- CSS
- Template(如jsp、Thymeleaf,通过${ooo}(#{ooo},即Template模板)获取数据)
- 双向数据绑定
- M层(数据)会通过VM层去跟V层(前端,即html、css、Template)进行双向数据绑定。
- 情况1:VM层会去监听M层(数据),如果M层(数据)发生了改变,那么V层也要发生变化。M是1,V显示为1;当M变成2,V显示为2。
- 情况2:VM层会去监听V层(前端,即html、css、Template),如果V层(前端,即html、css、Template)发生了改变,那么M层(数据)也要发生变化。
- M层(数据)会通过VM层去跟V层(前端,即html、css、Template)进行双向数据绑定。
- VM - ViewModle
- JavaScript
- Runtime:即时运行。当M变成2,V及时显示为2。
- Compiler:即时编译。当M变成2,V及时显示为2。
- ajax & json
- ajax请求java业务逻辑(数据库),java业务逻辑(数据库)返回json数据。
- M - Model
- java业务逻辑层
- 数据库
- java业务逻辑层
- V - View
- mvvm双向数据绑定的工作流程:
- 第一步:v层(view)与vm层(viewModel)进行双向数据绑定(操作虚拟dom,页面显示快、流畅;区别于js使用document来操作真实的dom元素,页面显示卡顿。)
- 第二步:vm层通过ajax访问java后台(数据库),java后台(数据库)返回json数据。
六 第一个vue程序(vue是MVVM 模式的实现者,他的核心就是实现了 DOM 监听 与 数据绑定)
- 环境准备
- 第一步:创建vue工程(文件夹)
- 第二步:使用vscode的open project(目录)打开工程
- 第三步:官网下载vue.js
- 开发版本
- 包含完整的警告和调试模式:https://vuejs.org/js/vue.js
- 删除了警告,30.96KB min + gzip:https://vuejs.org/js/vue.min.js
- CDN(在线,即在线的CDN)
- <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"> </script>:min.js是压缩版的,就一行代码。
- <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>:这个是完整版的代码。
- 开发版本
- 注 意:如果是idea,需要安装vue插件
- 开发
- 第一步:新建demo1.html
- 第二步:导包(要用vue,就要导包),使用在线的cdn方式:<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
- 第三步:<script></script>
- 第1步:创建vue对象(VM层,监听,即双向数据绑定)
- 第(1)步:el:绑定元素,相当于document.getElementById()
- 第(2)步:data对象:键值对(M层,即数据)
- 第(3)步:method方法:方法必须定义在method中。键值对。
- 第1步:创建vue对象(VM层,监听,即双向数据绑定)
- 第四步:html标签(V层)
- 第1步:使用{{}}({{}},即Template模板),获取data对象中的数据
- 第五步:浏览器
- 第1步:演示双向数据绑定
七 基础语法
- 指令:v- 开头
- v-bind:除了使用插值表达式{{}}进行数据渲染,也可以使用 v-bind指令,它的简写的形式就是一个冒号(:)
- 手动:我们在控制台操作对象属性,界面可以实时更新!
- 自动:我们还可以使用 v-bind 来绑定元素特性 !
- 案例:
<body><div id="app"><!--如果要将模型数据绑定在html属性中,此时title中显示的是模型数据--><h1 v-bind:title="message">鼠标悬停几秒钟查看此处动态绑定的提示信息!</h1><!-- v-bind 指令的简写形式: 冒号(:) --><h1 :title="message">我是标题</h1></div><script>new Vue({el: '#app',data: {message: '页面加载于 ' + new Date().toLocaleString()}})</script></body>
- v-if 系列
- v-if
- v-else-if
- v-else
- 案例
<body><div id="app"><!--=== 三个等号在 JS 中表示绝对等于(就是数据与类型都要相等)--><h1 v-if="type === 'A'">A</h1><h1 v-else-if="type === 'B'">B</h1><h1 v-else-if="type === 'C'">C</h1><h1 v-else>who</h1></div><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script><script>var vm = new Vue({el: '#app',data: {type: 'A'}})</script> </body>
- v-for
<body><div id="app"><li v-for="item in items">{{ item.message }}</li></div><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script><script>var vm = new Vue({el: '#app',data: {//items数组items: [{message: '狂神说Java'},{message: '狂神说前端'}]}}); </script> </body>
- v-bind:除了使用插值表达式{{}}进行数据渲染,也可以使用 v-bind指令,它的简写的形式就是一个冒号(:)
八 事件:v-on,我们可以使用 v-on
指令 (简写为 @
) 来监听 DOM 事件,并在事件触发时执行对应的 JavaScript(方法、函数)。
<body><div id="app"><!--在这里我们使用了 v-on 绑定了 click 事件并指定了名为 sayHi 的方法--><button v-on:click="sayHi">点我</button><!-- v-on 指令的简写形式 @ --><button @click="sayHi">点我</button></div><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script><script>var vm = new Vue({el: '#app',data: {message: 'Hello World'},// 方法必须定义在 Vue 实例的 methods 对象中// 这里必须传递一个事件对象eventmethods: {sayHi: function (event) {// `this` 在方法里指向当前 Vue 实例alert(this.message);}}});</script>
</body>
九 双向数据绑定:Vue.js的精髓之处:v-model
- Vue.js的精髓之处:
- Vue.js是一个MVVM框架,即数据双向绑定。
- 即当数据发生变化的时候,视图也就发生变化。
- 而当视图发生变化的时候,数据也会跟着同步变化。
- Vue.js是一个MVVM框架,即数据双向绑定。
- 在表单中使用双向数据绑定
- 你可以用v-model指令在表单<input> 、<textarea> 及<select>元素上创建双向数据绑
定。 - 它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但v-model本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
- 案例1:<input>、<textarea>
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-model="http://www.w3.org/1999/xhtml"xmlns:v-model.trim="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>狂神说java</title><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script></head><body><div id="app">输入的文本:<input type="text" v-model="message"> <br/>输入的文本是:{{message}}</div><script>new Vue({el: '#app',data: {message: '123'}})</script></body> </html>
- 案例2:<redio>、<checkbox>
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-model="http://www.w3.org/1999/xhtml"xmlns:v-model.trim="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>狂神说java</title><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script></head><body><div id="app">性别:男<input type="radio" value="男" v-model="kuangshen"> 女<input type="radio" value="女" v-model="kuangshen"><br/> 选中的是:{{kuangshen}}</div><script>new Vue({el: '#app',data: {kuangshen: '女' //将Vue实例的数据作为数据来源}})</script></body> </html>
- 案例3:<select>
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-model="http://www.w3.org/1999/xhtml"xmlns:v-model.trim="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>狂神说java</title><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script></head><body><div id="app">下拉框:<select v-model="kuangshen"><option value="" disabled>--请选择--</option><option>A</option><option>B</option><option>C</option></select><br/>选择中的值:{{kuangshen}}</div><script>new Vue({el: '#app',data: {kuangshen: 'B'}})</script></body> </html>
- 注意1: v-model会忽略所有表单元素的value、checked、selected 特性的初始值,而总是将Vue实例的数据作为数据来源。你应该通过JavaScript在组件的data选项中声明初始值!
- 你可以用v-model指令在表单<input> 、<textarea> 及<select>元素上创建双向数据绑
- 注意事项
- 注意1:值得注意的是,我们所说的数据双向绑定,一定是对于UI控件来说的,非UI控件不会涉及到数据双向绑定。单向数据绑定是使用状态管理工具的前提。如果我们使用vuex ,那么数据流也是单项的,这时就会和双向数据绑定有冲突。
- 注意2:在Vue.js中,如果使用vuex,实际上数据还是单向的,之所以说是数据双向绑定,这是用的UI控件来说,对于我们处理表单,Vue.js的双向数据绑定用起来就特别舒服了。即两者并不互斥,在全局性数据流使用单项,方便跟踪;局部性数据流使用双向,简单易操作。
十 组件
- 业务:通常一个应用会以一棵嵌套的组件树的形式来组织(这和我们嵌套 HTML 元素的方式类似)。
- 需求:组件可复用(html标签是复用的)。
- 思路、想:组件是可复用的 Vue 实例,说白了就是一组可以重复使用的模板,跟 html / JSTL 的自定义标签(如自定义一个标签<kuangshen></kuangshen>,然后可以复用在html页面中)、Thymeleaf 的 th:fragment 等框架有着异曲同工之妙。
- 组织结构:
- 案例1:
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-model="http://www.w3.org/1999/xhtml"xmlns:v-model.trim="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>狂神说java</title><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script></head><body><div id="app"><ul><!-- 有点类似自定义标签 --><kuangshen-component-li></kuangshen-component-li></ul></div><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script><script>// 先注册组件Vue.component('kuangshen-component-li', { // 名称template: '<li>Hello li</li>' // 模板,其实就是由多个html标签组成的});// 再实例化 Vuevar vm = new Vue({el: '#app'});</script></body> </html>
案例2:
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-model="http://www.w3.org/1999/xhtml"xmlns:v-model.trim="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>狂神说java</title><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script></head><body><div id="app"><ul><!--第一步:写上组件<kuangshen-component-li></kuangshen-component-li>,即代表template属性中的内容。问题:template属性中<li>标签之间要求有数据?答:而数据从items数组来。 --><!--第二步:v-for="item in items"循环获取items数组中的每个数据,每一项数据的别名都叫item。--><!--第三步:使用v-bind获取for循环中的每一个数据(item),并绑定组件对象中props属性列表中的参数panshengbo。--><kuangshen-component-li v-for="item in items" v-bind:panshengbo="item"></kuangshen-component-li></ul></div><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script><script>Vue.component('kuangshen-component-li', { //第四步:问题:直接写'<li>{{panshengbo}}</li>'是获取不了数据“panshengbo”的,我们需要通过一个参数去接收,即props。// props:['panshengbo']用于接收传输过来的数据。// 如果你不用props,你是无法直接接收外面的数据的。props:['panshengbo'],//第五步:template的<li>中使用{{panshengbo}}来传输过来的每个数据。template: '<li>{{panshengbo}}</li>' });var vm = new Vue({el: '#app',data:{items:["java","linux","前端"]}});</script></body> </html>
与vue的关系:
如下图,是xxx.vue文件的组织形式:
从上面的xxx.vue文件的组织方式、组件基础的知识,可以看出,xxx.vue和组件都有一个共同的标签,那就是<template>吧。到此,总算和vue粘一点边了。
十一 vue的生命周期(钩子函数)
- 在 Vue 的整个生命周期中,它提供了一系列的事件(开始创建、初始化数据、编译模板、挂载 DOM、渲染→更新→渲染、卸载等)。
- 可以让我们在事件触发时注册 JS 方法,可以让我们 用自己注册的 JS 方法控制整个大局。
- 在这些事件响应方法中的 this 直接指向的是 Vue 的实例。
十二 axios异步通信
- Axios 概述
- 原因:
- 少用 jQuery,因为它操作Dom太频繁!
- 定义:
- 【官网】易用、简洁且高效的http库
- 作用:
- Axios 是一个开源的可以用在浏览器端和 NodeJS 的异步通信框架,它的主要作用就是实现 AJAX 异步通信。
- 特点:
- 从浏览器中创建 XMLHttpRequests
- 从 node.js 创建 http 请求
- 支持 Promise API [ JS中链式编程 ]
- 拦截请求和响应
- 转换请求数据和响应数据
- 取消请求
- 自动转换 JSON 数据
- 客户端支持防御 XSRF(跨站请求伪造)
- 地址:
- GitHub:https://github.com/axios/axios
- 中文文档:http://www.axios-js.com/
- 注意事项
- idea设置为支持es6规范的(不然代码会报编译异常)
- 浏览器必须是支持es6规范的
- 原因:
- 案例1:data.json、demo7.html 只取数据
{"name":"狂神说java","url": "http://baidu.com","page": "1","isNonProfit":"true","address": {"street": "含光门","city":"陕西西安","country": "中国"},"links": [{"name": "B站","url": "https://www.bilibili.com/"},{"name": "4399","url": "https://www.4399.com/"},{"name": "百度","url": "https://www.baidu.com/"}]}
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-model="http://www.w3.org/1999/xhtml"xmlns:v-model.trim="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>狂神说Java</title></head><body><div id="app"></div><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script><script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><script type="text/javascript">var vm = new Vue({el:'#app',mounted() { // 第一步:钩子函数// 第二步:axiosn发送异步请求,获取json文件的数据,并在控制台打印axios.get('data.json').then(response => (console.log(response.data)));}});</script></body> </html>
- 案例2:data.json demo7.html 渲染数据
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-model="http://www.w3.org/1999/xhtml"xmlns:v-model.trim="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>狂神说Java</title></head><body><div id="app"><div>{{info.name}}</div><div>{{info.address.street}}</div><!-- 数据绑定到属性 --><a v-bind:href="info.url">听我</a></div><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script><script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script><script type="text/javascript">var vm = new Vue({el:'#app',data(){ // 功能相当于data属性return{// 这个地方只是摆格式,并没有真正的数据。// 而且这里的格式,必须和json字符串格式一样info:{name:null,url:null,address:{street:null,city:null,country:null}}}},mounted() { // 第一步:钩子函数// 第二步:axios发送异步请求,获取json文件的数据,并且数据取名为info// 第三步:data(){return中的info}用于接收axios返回的数据axios.get('data.json').then(response => (this.info = response.data));}});</script></body> </html>
- 注意事项
- vue的闪烁事件
- 谷歌浏览器报:Access to XMLHttpRequest at ‘fileDxxxxx.json‘ from origin ‘null‘ has been blocked by CORS问题解决
十三 计算属性
- 定义:计算(动词)+ 属性(名词)
- 需求:
- 内存中运行:虚拟Dom,速度快
- 计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销;
- 解决方案:计算属性
- 思想路:
- 将计算出来的结果保存到一个属性中,可以想象成缓存!
- 案例
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-model="http://www.w3.org/1999/xhtml"xmlns:v-model.trim="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>狂神说Java</title></head><body><div id="app"><div>{{message}}</div><!-- 调用方法 --><div>{{currentTime1()}}</div><!-- 计算属性(区别于调用方法) --><div>{{currentTime2}}</div></div><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script><script type="text/javascript">var vm = new Vue({el:'#app',data: {// 方案1:普通属性(注意区别于计算属性)message: 'Hello Vue'},methods: {// 方案2:调用方法currentTime1: function () {return Date.now();}},computed: {// 方案3:计算属性(注意区别于普通属性)//currentTime2 ,这是一个属性!不是方法currentTime2: function () {this.message;// 优点:此数据被改变后,计算属性会自动重新计算return Date.now();}}});//注意:methods和computed中的方法名可重名,重名后只会调用methods中的方法</script></body> </html>
十四 插槽slot:内容分发
- 思想路
- 正常情况下,我们会直接使用数据渲染整个页面。
- 特殊情况下,页面只会变某个部。此时可以在页面中留出两个口(这两个口就叫做插槽),方便在里面插入东西,而且是动态地可拔插,重点是复用性。如下图所示:
- 案例:比如准备制作一个待办事项组件(todo),该组件由待办标题(todo-title)和待办内容(todo-items)组成,但这三个组件又是相互独立的,该如何操作呢?
- 数据写死
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-model="http://www.w3.org/1999/xhtml"xmlns:v-model.trim="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>狂神说Java</title></head><body><div id="app"><!-- 第四步:使用插槽 --><todo><todo-title></todo-title><todo-items></todo-items></todo></div><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script><script type="text/javascript">// 第一步: 定义一个待办事项的组件Vue.component('todo_0', {template: '<div>\<div>待办事项</div>\<ul>\<li>学习狂神说Java</li>\</ul>\</div>'});// 第二步: 我们需要让待办事项的标题和值实现动态绑定,怎么做呢? 我们可以留出2个插槽(标题插槽、列表插槽)!// 1、将上面的代码留出2个插槽(标题插槽、列表插槽),即 slotVue.component('todo', {template: '<div>\<slot></slot>\<ul>\<slot></slot>\</ul>\</div>'});// 2、定义一个名为 todo-title 的待办标题组件 和 todo-items 的待办内容组Vue.component('todo-title', {template: '<div>标题</div>'});Vue.component('todo-items', {template: '<li>java lanaguage123</li>'});var vm = new Vue({el:'#app'});</script></body> </html>
使用自定义的数据
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-model="http://www.w3.org/1999/xhtml"xmlns:v-model.trim="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>狂神说Java</title></head><body><div id="app"><!-- 第四步:将这些值,通过插槽插入 --><todo><todo-title slot="todo-title" title="秦老师系列课程"></todo-title><todo-items slot="todo-items" v-for="(item, index) in todoItems"v-bind:item="item" v-bind:index="index"></todo></div><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script><script type="text/javascript">// 第一步: 定义一个待办事项的组件Vue.component('todo_0', {template: '<div>\<div>待办事项</div>\<ul>\<li>学习狂神说Java</li>\</ul>\</div>'});// 第二步: 我们需要让待办事项的标题和值实现动态绑定,怎么做呢? 我们可以留出2个插槽(标题插槽、列表插槽)!// 1、将上面的代码留出2个插槽(标题插槽、列表插槽),即 slotVue.component('todo', {template: '<div>\<slot name="todo-title"></slot>\<ul>\<slot name="todo-items"></slot>\</ul>\</div>'});// 2、定义一个名为 todo-title 的待办标题组件 和 todo-items 的待办内容组Vue.component('todo-title', {props: ['title'], // 接收传到组件的动态数据:title属性template: '<div>{{title}}</div>' // 使用title属性});//这里的index,就是数组的下标,使用for循环遍历的时候,可以循环出来!Vue.component('todo-items', {props: ['item', 'index'], // 接收传到组件中的动态:item、index属性template: '<li>{{index + 1}}. {{item}}</li>' // 使用item、index属性});// 3、实例化 Vue 并初始化数据var vm = new Vue({el:'#app',data: {todotitle:"学生选课",todoItems: ['狂神说Java1', '狂神说运维', '狂神说前端']}});</script></body> </html>
- 数据写死
十五 自定义事件内容分发
- 业务:点击“删除”按钮,把li列表中的项目删除
- 方案1:缺点组件中无法调用vue实例中的方法,只能调用本组件中定义的方法:
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-model="http://www.w3.org/1999/xhtml"xmlns:v-model.trim="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>狂神说Java</title></head><body><div id="app"><todo><todo-title slot="todo-title" title="秦老师系列课程"></todo-title><todo-items slot="todo-items" v-for="item in todoItems"v-bind:item="item"></todo></div><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script><script type="text/javascript">Vue.component('todo_0', {template: '<div>\<div>待办事项</div>\<ul>\<li>学习狂神说Java</li>\</ul>\</div>'});Vue.component('todo', {template: '<div>\<slot name="todo-title"></slot>\<ul>\<slot name="todo-items"></slot>\</ul>\</div>'});Vue.component('todo-title', {props: ['title'], template: '<div>{{title}}</div>' });Vue.component('todo-items', {props: ['item', 'index'], // 调用成功 template: '<li>{{item}}<button @click="remove">删除</button></li>', // 调用失败 //template: '<li>{{index + 1}}. {{item}}<button @click="removeItems">删除</button></li>', methods:{remove:function(){alert(111);}}});var vm = new Vue({el:'#app',data: {todotitle:"学生选课",todoItems: ['狂神说Java1', '狂神说运维', '狂神说前端']},methods:{// 该方法可以被模板中自定义事件触发removeTodoItems: function (index) {console.log("删除 " + this.todoItems[index] + " 成功");// splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目// 其中 index 为添加/删除项目的位置,1 表示删除的数量this.todoItems.splice(index, 1);}}});</script></body> </html>
- 方案2:理一下思路:
<!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-model="http://www.w3.org/1999/xhtml"xmlns:v-model.trim="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>狂神说Java</title></head><body><div id="app"><todo><todo-title slot="todo-title" title="秦老师系列课程"></todo-title><todo-items slot="todo-items" v-for="(item, index) in todoItems"v-bind:item="item" v-bind:index="index" v-on:remove="removeTodoItems(index)"><!-- v-on:用于绑定vm实例中的方法--> <!-- 自定义事件的名称:removeTodoItems。--><!-- 参数:(index)。 --></todo></div><script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script><script type="text/javascript">Vue.component('todo_0', {template: '<div>\<div>待办事项</div>\<ul>\<li>学习狂神说Java</li>\</ul>\</div>'});Vue.component('todo', {template: '<div>\<slot name="todo-title"></slot>\<ul>\<slot name="todo-items"></slot>\</ul>\</div>'});Vue.component('todo-title', {props: ['title'], template: '<div>{{title}}</div>' });Vue.component('todo-items', {props: ['item', 'index'], template: '<li>{{index + 1}}. {{item}}<button @click="remove">删除</button></li>', methods:{// 自定义事件内容分发。// 使用调用此方法时,实际上调用的是vm实例中的removeTodoItems方法。remove:function(index){// 这里的 remove 是自定义事件的名称,需要在 HTML 中使用 v-on:remove 的方式指派this.$emit('remove', index);}}});var vm = new Vue({el:'#app',data: {todotitle:"学生选课",todoItems: ['狂神说Java1', '狂神说运维', '狂神说前端']},methods:{// 该方法可以被模板中自定义事件触发removeTodoItems: function (index) {console.log("删除 " + this.todoItems[index] + " 成功");// splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目// 其中 index 为添加/删除项目的位置,1 表示删除的数量this.todoItems.splice(index, 1);}}});</script></body> </html>
- 方案1:缺点组件中无法调用vue实例中的方法,只能调用本组件中定义的方法:
十六 第一个vue-cli项目
- 脚手架定义
- 以前,我们在搭建一个项目的时候,项目开始前会用SSM做骨架。如果把SSM做的骨架抽出来,那它便成了一个脚手架。脚手架的作用是:基于脚本手(骨架),我们可以进行快速地进行开发。就好比咱们在idea中创建 Maven 项目时可以选择创建一个骨架项目(模板项目),这个骨架项目(模板项目)就是脚手架,使得我们的开发更加的快速;如下图所示:
- 以前,我们在搭建一个项目的时候,项目开始前会用SSM做骨架。如果把SSM做的骨架抽出来,那它便成了一个脚手架。脚手架的作用是:基于脚本手(骨架),我们可以进行快速地进行开发。就好比咱们在idea中创建 Maven 项目时可以选择创建一个骨架项目(模板项目),这个骨架项目(模板项目)就是脚手架,使得我们的开发更加的快速;如下图所示:
- vue-cli定义
- vue官方提供的一个脚手架,用于快速生成一个 vue 的项目模板:
- 预先定义好的目录结构及基础代码:
- 统一的目录结构:跟咱们的maven项目一样,.java类一定要写在/src/main/java这个目录下面。你的配置文件,一定是放在项目根目录的resources目录下面。
- 统一的基础代码:跟maven一样,如maven会自动生成程序入口类。
- 本地调试:跟maven一样。
- 热部署:跟maven一样。
- 单元测试:跟maven一样。
- 集成打包上线: 跟maven一样。
- vue官方提供的一个脚手架,用于快速生成一个 vue 的项目模板:
- npm与maven的区别与联系
- npm去下载那些安装的时候,npm干的就是maven干的事情呀,你可以把npm想象成maven的包管理模块。但npm跟maven也是有区别的:npm更偏向于linux系统的操作,如果以前使用linux的话,你会发现npm的很多操作命令和linux命令都差不多,包括在线安装一些东西呀等等。
- vue-cli环境搭建
- 第一步:安装Node.js(自带npm,可直接用npm了。自动帮我们配置环境变更,Add to Path。)
- node -v
- npm -v
- 全局安装 npm install xxx的默认目录是:
- 第二步:安装Git(不是必须)
- 第三步:安装node.js淘宝镜像加速器(cnpm)。我们是不是听了好多次镜像加速器这个东西啦,那个maven是不是也是这样的。maven的中央仓库本来是在国外的,用了阿里巴巴的镜像加速器,就快很多,不然你从国外的maven中央仓库下载,那得多慢呀。同理,npm下载安装的东西,也是国外的仓库地址。如果你想加快一点速度,那只能用国内的cnpm,还是阿里的东西。但cnpm它有一些问题,有些用cnpm下载安装的包,放到项目里是能用,但在打包的时候可能就会发生各种莫名其妙的错误。所以能用npm就尽量用,实在不行再用cnpm。
- 第四步:安装vue -cl
- # 测试是否安装成功# 查看可以基于哪些模板创建 vue 应用程序,通常我们选择 webpackvue list
- browserify
- browserify-simple
- pwa
- simple
- webpack:一般的vue项目,我们都会通过webpack来创建。因为vue是基于es6的开发,但真正网站使用时很多还是基于es5的,我们通过使用webpack把es6的语法降级(转换)成大多数浏览器都支持的es5语法。
- webpack-simple
- 创建运行,第1个vue-clie程序:相当于java程序中的helloworld
- 第一步:管理员模式下,cmd命令输入框
- 第二步:cd进入到某个目录
- 第三步:执行命令vue init webpack myvue ,即初始化一个webpack的vue项目,效果是在该目录下自动生成一个vue - webpack项目(名字叫myvue):
- 第四步:cd myvue
- 第五步:npm install:在当前目录下,安装此webpack模板的vue项目的所有依赖环境。npm install安装哪些呢?它根据的是配置文件pack.json中要求的进行安装的。安装的目录是,项目根目录下的node_modules目录:
- 第六步:等待npm install加载安装完成,说明这个项目初始化完毕了,初始化完毕就可以直接运行了。但这只是一个基础的前端工程,就相当于java的helloword。
- 修复:npm audit fix(run 'npm audit fix' to fix them,or 'npm audit' for details)
- 第七步:npm run dev。用于启动并运行此项目,相当于我们使用命令启动tomcat并开启8080端口那样。
- 第1步:告诉我们,自动编译整个项目,编译之后才能打包,即 xx building modules xxx
- 第2步:告诉我们,自动打包整个项目,打包之后才能启动并运行, webpack-dev-server --inline --progress --config build/webpack.dev.conf.js
- 第3步:告诉我们,编译并打包完成,DONE Compiled successfully in 3221ms
- 第4步:告诉我们,访问的路径:Your application is running here: http://localhost:8080
- 第八步:访问此前端项目:Your application is running here: http://localhost:8080,前端项目的首页是vuejs的标识,而tomcat项目的首页是一个猫。
- 第九步:停止项目:ctrl + c Y,相当于tomcat的shutdown
- 项目详解,第1个vue-clie程序
- 第一步:使用vs code打开项目(文件夹),因为它是一个前端项目
- 第二步:查看项目的结构
- build目录:构建
- build.js ---- 这个地方就是一些构建的一些信息,最终我们会用npm命令执行它是吧。
- check-version.js ---- 检查所有东西的版本,如检查npm、node.js版本。
- webpack.base.conf.js ---- webpack基本配置。webpack是不是就是咱们打包相关的,我们运行(npm run dev)之前,就是使用它来打包的。
- webpack.dev.conf.js ----- webpack开发环境配置
- webpack.prod.conf.js ---- webpack生产环境配置
- config目录:配置目录,包括端口号等。我们初学可以使用默认的。
- dev.env.js:开发环境变量
- prod.env.js:生产环境变量
- index.js:配置变量
- node_modules目录:包含我们使用npm install下载安装的东西,即这个程序运行起来需要的所有组件。相当于咱们java里面的lib目录,只是这里下载的不是.jar包,而是一些依赖。
- src目录:放源码的地方
- assets:资源文件,比如存放 css,图片等资源。
- component:组件文件夹,用来存放 vue 的公共组件(注册于全局,在整个项目中通过关键词便可直接输出)。
- app.vue:是项目的主组件,所有页面都是在该组件下进行切换的。
- main.js:入口文件(入口程序)。是项目的入口文件,作用是初始化 vue 实例,并引入所需要的插件。
- static目录:静态资源目录,如图片、字体等。
- index.html:项目的首页入口文件,你可以添加一些 meta 信息或统计代码啥的。
- package.json:node配置文件,记载着一些命令、依赖及其版本、简要的项目描述信息
- 比如,npm run dev命令
- build目录:构建
- 附1:package.json详解
{// 项目/模块名称,长度必须小于等于 214 个字符,不能以"."(点)或者"_"(下划线)开头,不能包含大写字母"name": "myvue",// 项目版本"version": "1.0.0",// 项目描述"description": "project",// 作者"author": "Demo_Null",// 是否私有,设置为 true 时,npm 拒绝发布"private": true,// 执行 npm 脚本命令简写,执行前面的简写就代表执行后面的命令"scripts": {"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js","start": "npm run dev","unit": "jest --config test/unit/jest.conf.js --coverage","e2e": "node test/e2e/runner.js","test": "npm run unit && npm run e2e","lint": "eslint --ext .js,.vue src test/unit test/e2e/specs","build": "node build/build.js"},// 生产环境下,项目运行所需依赖"dependencies": {"vue": "^2.5.2","vue-router": "^3.0.1"},// 开发环境下,项目所需依赖"devDependencies": {"autoprefixer": "^7.1.2","babel-core": "^6.22.1","babel-eslint": "^8.2.1","babel-helper-vue-jsx-merge-props": "^2.0.3","babel-jest": "^21.0.2","babel-loader": "^7.1.1","vue-style-loader": "^3.0.1","vue-template-compiler": "^2.5.2","webpack": "^3.6.0","webpack-bundle-analyzer": "^2.9.0","webpack-dev-server": "^2.9.1","webpack-merge": "^4.1.0"},// 项目运行的平台"engines": {"node": ">= 6.0.0","npm": ">= 3.0.0"},// 供浏览器使用的版本列表"browserslist": ["> 1%","last 2 versions","not ie <= 8"] }
- 附2:index.js 详解
'use strict' //---严格的语法const path = require('path') //---node.js路径模块module.exports = {dev: {// PathsassetsSubDirectory: 'static', //---配置静态目录的地方。相当于tomcat目录中的web-info目录。assetsPublicPath: '/',proxyTable: {},// Various Dev Server settingshost: 'localhost', // can be overwritten by process.env.HOSTport: 8080, //---配置端口号 autoOpenBrowser: false,//项目运行时是否自动打开浏览器errorOverlay: true,// 浏览器错误提示notifyOnErrors: true,// 跨平台错误提示poll: false, // 使用文件系统获取文件改动的通知devServer.watchOptions https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-// Use Eslint Loader?// If true, your code will be linted during bundling and// linting errors and warnings will be shown in the console.useEslint: false,// If true, eslint errors and warnings will also be shown in the error overlay// in the browser.showEslintErrorsInOverlay: false,/*** Source Maps*/// https://webpack.js.org/configuration/devtool/#developmentdevtool: 'cheap-module-eval-source-map', // 增加调试,该属性为原始源代码// If you have problems debugging vue-files in devtools,// set this to false - it *may* help// https://vue-loader.vuejs.org/en/options.html#cachebustingcacheBusting: true, // 使缓存失效cssSourceMap: true // 代码压缩后bug定位将非常困难,引入SourceMap记录压缩前后的位置信息记录,当产生错误时直接定位到压缩前的位置},//生产环境build: {// Template for index.htmlindex: path.resolve(__dirname, '../dist/index.html'),// 编译输入的index.html文件// PathsassetsRoot: path.resolve(__dirname, '../dist'),// 编译输出的静态资源路径(项目打包时的文件)assetsSubDirectory: 'static',// 编译输出的二级目录assetsPublicPath: '/',// 编译发布的根目录,可配置为资源服务器域名或CDN域名/*** Source Maps*/productionSourceMap: true, // 是否开启cssSourceMap// https://webpack.js.org/configuration/devtool/#productiondevtool: '#source-map', // 增加调试,该属性为原始源代码// Gzip off by default as many popular static hosts such as// Surge or Netlify already gzip all static assets for you.// Before setting to `true`, make sure to:// npm install --save-dev compression-webpack-pluginproductionGzip: false,// 是否开启gzipproductionGzipExtensions: ['js', 'css'], // 需要使用gzip压缩文件的扩展名// Run the build command with an extra argument to// View the bundle analyzer report after build finishes:// `npm run build --report`// Set to `true` or `false` to always turn it on or offbundleAnalyzerReport: process.env.npm_config_report // 打包分析} } //原文链接:https://blog.csdn.net/yhj198927/article/details/124044693
- 附3:build.js 详解
'use strict' //---严格模式 require('./check-versions')() //---npm和node版本检查并立即执行,请看我的check-versions配置文件解释文章process.env.NODE_ENV = 'production' //---process是node中的global全局对象的属性,process是node中的全局变量,env设置环境变量。此设置环境为生产环境productionconst ora = require('ora') //---ora是一个命令行转圈圈动画插件,好看用的 const rm = require('rimraf') //---rimraf插件是用来执行UNIX命令rm和-rf的用来删除文件夹和文件,清空旧的文件 const path = require('path') //---node.js路径模块 const chalk = require('chalk') //---chalk插件,用来在命令行中输入不同颜色的文字 const webpack = require('webpack') //---引入webpack模块使用内置插件和webpack方法 const config = require('../config') //---引入config下的index.js配置文件,此配置文件我之前介绍了请自行查阅,主要配置的是一些通用的选项 const webpackConfig = require('./webpack.prod.conf') //---下面是生产模式的webpack配置文件,请看我的webpack.prod.conf解释文章const spinner = ora('building for production...') //---开启转圈圈动画 spinner.start() //---开始执行加载动画//---调用rm方法,第一个参数的结果就是 dist/static,表示删除这个路径下面的所有文件 rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {if (err) throw err //---如果删除的过程中出现错误,就抛出这个错误,同时程序终止webpack(webpackConfig, (err, stats) => { //---没有错误,就执行webpack编译//---这个回调函数是webpack编译过程中执行spinner.stop() //---停止转圈圈动画if (err) throw err //---如果有错误就抛出错误process.stdout.write(stats.toString({ //---没有错误就执行下面的代码,process.stdout.write和console.log类似,输出对象//---stats对象中保存着编译过程中的各种消息colors: true, //---增加控制台颜色开关modules: false, //---不增加内置模块信息children: false, //---不增加子级信息chunks: false, //---允许较少的输出chunkModules: false //---不将内置模块的信息加到包信息}) + '\n\n')if (stats.hasErrors()) {console.log(chalk.red(' Build failed with errors.\n'))process.exit(1)}//---以上就是在编译过程中,持续打印消息//---下面是编译成功的消息console.log(chalk.cyan(' Build complete.\n'))console.log(chalk.yellow(' Tip: built files are meant to be served over an HTTP server.\n' +' Opening index.html over file:// won\'t work.\n'))}) }) // end // 注: 如果你想自己编写一个高质量的脚手架工具,建议你: // 去补习nodejs,然后补习 es6,然后再来看webpack官方文档,然后自己独立编写一个和vue-cli类似的脚手架,如果上面的东西看不懂,更要这样做 // vue-cli还有一部分内容是关于代码测试的,可以说这块内容的复杂度不亚于webpack,这些内容对nodejs要求比较熟悉,说白了就是基础弱的很难入门,但是测试这块内容也是非常有价值的,可以借助无界面的浏览器解析引擎,通过一句命令就可以把你的代码在不同的平台上运行,还能指出问题所在,所以,我会渐渐的转战nodejs去了,后续的文章将很多是关于nodejs的文章,如果感兴趣的可以关注我的文章,一起学习探讨 //原文链接:https://blog.csdn.net/song854601134/article/details/120598334
- 附4:webpack.base.conf.js 详解,我们maven里面build result是不是也干这个事情,build result可以过滤xml让xml出去呀。也就是说此文件所配置的东西就是跟打包相关的信息,是不是跟maven特别像呀。
'use strict' const path = require('path') //---引入nodejs路径模块 const utils = require('./utils') //---引入utils工具模块,具体查看我的博客关于utils的解释,utils主要用来处理css-loader和vue-style-loader的 const config = require('../config') //---引入config目录下的index.js配置文件,主要用来定义一些开发和生产环境的属性 const vueLoaderConfig = require('./vue-loader.conf') //---vue-loader.conf配置文件是用来解决各种css文件的,定义了诸如css,less,sass之类的和样式有关的loaderfunction resolve (dir) { //---此函数是用来返回当前目录的平行目录的路径,因为有个'..'return path.join(__dirname, '..', dir) }module.exports = {context: path.resolve(__dirname, '../'),entry: {app: './src/main.js' //---入口文件是src目录下的main.js},output: {path: config.build.assetsRoot, //---输出路径是config目录下的index.js中的build配置中的assetsRoot,也就是dist目录filename: '[name].js', //---项目输出文件名称,这里使用默认的name也就是main。publicPath: process.env.NODE_ENV === 'production' //---上线地址,也就是真正的文件引用路径,如果是production生产环境,其实这里都是 '/'? config.build.assetsPublicPath: config.dev.assetsPublicPath},resolve: {// resolve是webpack的内置选项,顾名思义,决定要做的事情,也就是说当使用 import "jquery",该如何去执行这件事// 情就是resolve配置项要做的,import jQuery from "./additional/dist/js/jquery" 这样会很麻烦,可以起个别名简化操作extensions: ['.js', '.vue', '.json'], // 省略扩展名,也就是说.js,.vue,.json文件导入可以省略后缀名,这会覆盖默认的配置,所以要省略扩展名在这里一定要写上alias: {//后面的$符号指精确匹配,也就是说只能使用 import vuejs from "vue" 这样的方式导入vue.esm.js文件,不能在后面跟上 vue/vue.js'vue$': 'vue/dist/vue.esm.js',// resolve('src') 其实在这里就是项目根目录中的src目录,使用 import somejs from "@/some.js" 就可以导入指定文件,是不是很高大上'@': resolve('src')}},// 以下是一些静态资源过滤规则,通过条件进行过滤// module用来解析不同的模块module: {rules: [{test: /\.(js|vue)$/,// 也就是说,对.js和.vue文件在编译之前进行检测,检查有没有语法错误loader: 'eslint-loader',// 此选项指定enforce: 'pre'选项可以确保,eslint插件能够在编译之前检测,如果不添加此项,就要把这个配置项放到末尾,确保第一个执行enforce: 'pre',// include选项指明这些目录下的文件要被eslint-loader检测,还有一个exclude表示排除某些文件夹include: [resolve('src'), resolve('test')],// options表示传递给eslint-loader的参数options: {// formatter是参数的名称,eslint-friendly-formatter是eslint的一个报告总结插件,也就是说eslint的检测报告非常难看懂,这个插件就是整理这些报告方便查阅的formatter: require('eslint-friendly-formatter')}},{test: /\.vue$/,// 对vue文件使用vue-loader,该loader是vue单文件组件的实现核心,专门用来解析.vue文件的loader: 'vue-loader',// 将vueLoaderConfig当做参数传递给vue-loader,就可以解析文件中的css相关文件options: vueLoaderConfig},{test: /\.js$/,// 对js文件使用babel-loader转码,该插件是用来解析es6等代码loader: 'babel-loader',// 指明src和test目录下的js文件要使用该loaderinclude: [resolve('src'), resolve('test')]},{test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,// 对图片相关的文件使用 url-loader 插件,这个插件的作用是将一个足够小的文件生成一个64位的DataURL// 可能有些老铁还不知道 DataURL 是啥,当一个图片足够小,为了避免单独请求可以把图片的二进制代码变成64位的// DataURL,使用src加载,也就是把图片当成一串代码,避免请求,神不神奇??loader: 'url-loader',options: {// 限制 10000 个字节一下的图片才使用DataURLlimit: 10000,// 下面这个应该是指将[name].[hash:7].[ext]对应的图片使用url-loader测试吧,这个我是真不知道干啥的,如果知道// 的兄弟,一定要留言给我啊,拜谢name: utils.assetsPath('img/[name].[hash:7].[ext]') // 这个函数执行结果是 /img/[name].[hash:7].[ext]// 不知道吧 name 设置成 /img/[name].[hash:7].[ext] 意欲何为,猜测应该是输出图片的路径或者是解析图片的路径}},{test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,// 字体文件处理,和上面一样loader: 'url-loader',options: {limit: 10000,name: utils.assetsPath('fonts/[name].[hash:7].[ext]')}}]} //原文链接:https://blog.csdn.net/song854601134/article/details/120598344?spm=1001.2014.3001.5502
- 附5:vue项目结构是怎么样的?详解vue目录结构! (w3cschool.cn)
十七 webpack学习使用(vuejs中的写法,就是这里的模块化处理)
- 业务
- 伴随着移动互联网的大潮,当今越来越多的网站已经从网页模式进化到了WebApp模式。也就是说,已经把网站当做一个单独的应用,并运行在浏览器里面。
- javascript模块化的演进
- 第1阶段:<script>标签
- 如<script src="module1.js"><script>。这是最原始的javascript文件加载方式,它把每一个文件都看做是一个模块,那么他们的接口通常是暴露在全局作用域下,也就是定义在window对象中,不同模块的调用都是一个作用域。缺陷明显,所以需要一些规范。
- 第2阶段:CommonsJS —— export & inport & require —— 同步阻塞加载
- 服务器端的NodeJS遵循CommonsJS规范,该规范核心思想是允许模块通过require方法来同步加载所需依赖的其它模块,然后通过exports或module.export1来导出需要暴露的接口。有优点,也有缺点。
- 优点:
●服务器端模块便于重用
●NPM中已经有超过45万个可以使用的模块包
●简单易用 - 缺点:
●同步的模块加载方式不适合在浏览器环境中,同步意味着阻塞加载,浏览器资源是异步加载的。更理想的方式是,异步非阻塞的模块加载方式。
●不能非阻塞的并行加载多个模块
- 优点:
- 服务器端的NodeJS遵循CommonsJS规范,该规范核心思想是允许模块通过require方法来同步加载所需依赖的其它模块,然后通过exports或module.export1来导出需要暴露的接口。有优点,也有缺点。
- 第3阶段:AMD —— define & require —— 异步非阻塞加载
- 第4阶段:CMD —— defind & export —— 模块的加载逻辑偏重
- 第5阶段:ES6模块 —— inport(导入) & export(暴露) & module(模块) —— 编译时错误检查
- ES6规范大家知道,现在的javascript基本上都是面对ES6规范在做的。但是浏览器不在ES5规范。
EcmaScript6标准增加了JavaScript语言层面的模块体系定义。ES6模块的设计思想是尽量静态化,使编译时就能确定模块的依赖关系,以及输入和输出的变量,增加编译检查与异常抛出(解决变量冲突),增加运行时异常(提供更多的错误信息)。CommonsJS和AMD模块,都只能在运行时确定这些东西,编译时啥都没做。
- ES6规范大家知道,现在的javascript基本上都是面对ES6规范在做的。但是浏览器不在ES5规范。
- 大家期望的模块化
- 可以兼容多种模块风格,尽量可以利用已有的代码,不仅仅只是JavaScript模块化,还有CSS、图片、字体等资源也需要模块化。
- webpack模块化处理
- webpack是一款模块加载器兼打包工具,它能把各种资源,如JS、JSX、ES6、SASS、LESS、图片等都作为模块来处理和使用。
- 第1阶段:<script>标签
- 需求
- 为了支持较低版本的浏览器,es6 转 es5。
- 依赖管理
- 流原
- webpack依赖管理功能原理
- 同maven depandence。
- webpack编译打包原理
- 前端的一键打包:当webpack处理应用程序时,它会递归地构建一个依赖关系图(dependency graph,package.json中的依赖),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle。“依赖关系图”这个像啥?是不是像我们的maven呀。父子依赖,对不对,一个父项目里面有子项目,子项目中依赖(dependence)了很多很多的东西。
- 同理 —— maven的一键打包命令:maven package命令一键生成jar 或 war包,不用我们手动在命令行一步一步去做了。
- webpack依赖管理功能原理
- 分类
- webpack在vue项目中的使用方式
- 自动化构建(编译打包)
- 在vue项目中有一个build目录,build目录下有一个webpack.base.conf.js文件,就是通过此文件对webpack的设置进行自动化构建(编译打包)。那么我们来看一下,怎么手动去做这件事情。。。。。。
- 手动构建(编译打包)
- 自动化构建(编译打包)
- webpack在vue项目中的使用方式
- 环境搭建
- 第一步:安装webpack
- npm install webpack -g,打包工具,全局的在哪个目录下安装都行,如果安装失败就改用cnpm去安装
- npm install webpack-cli -g,客户端,全局的在哪个目录下安装都行,如果安装失败就改用cnpm去安装
- 第二步:测试安装成功
- webpack -v
- webpack-cli -v
- 第三步:webpack版本调整
- 咱们来看pack.json里面,里面写了1个webpack版本。我们安装的webpack肯定是最新版本的webpack吧,而pack.json中写的版本往往不是最新的。因为版本不一致,所以在使用webpack进行打包时,可能会有一些东西打包不进去。这时,我们可能需要在pack.json中,调一调一某些依赖的版本,升一升版本,或者降一降版本。
- 第四步:配置webpack —— 创建webpack.config.js配置文件
- 了解:这些东西咱们不管,理解一下就好了
- entry,入口文件,指定WebPack用哪个文件作为项目的入口 —— 就只有一个,即我们的main.js。
- output,输出,指定WebPack把处理完成的文件放置到指定路径 —— 就是我们使用webpack打包完成后,会自动生成(输出)一个文件,你要把这个文件放到哪个位置。
- module,模块,用于处理各种类型的文件 —— 我们打包是不是要把一些模块打进去呀,我们的java程序也是这样的,生成.jar包的时候需要把它此java项目所有的依赖都安上去再打包。
- plugins,插件,如:热更新、代码重用等 —— plugins是一些插件,你要是放插件,它也可以实现啊。
- resolve,设置路径指向 ——
- watch,监听,用于设置文件改动后直接打包 ——
- 了解:这些东西咱们不管,理解一下就好了
- 第一步:安装webpack
- webpack的使用
- 狂神文档参考:
- 自己的详细操作步骤
- 第一步:在某个目录下创建一个文件夹webpack-study
- 第二步:使用vs code工具打开它webpack-study
- 第三步:vs code操作
- 第1步:创建 —— 一个名为modules的目录,用于放置JS模块等资源文件。
- 第2步:暴露 —— 在modules目录下创建模块文件,如hello.js, 用于编写JS模块相关代码。
// 哈哈 这个地方是给你补es6的语法啊// 第一步:exports,暴露一个方法(此方法执行完,会在前端生成一个h1标签,文字加粗) exports.sayHi = function(){document.write("<h1>狂神的es666</h1>") } exports.sayHi1 = function(){document.write("<h1>狂神的es6661</h1>") } exports.sayHi2 = function(){document.write("<h1>狂神的es6662</h1>") } exports.sayHi3 = function(){document.write("<h1>狂神的es6663</h1>") }
- 第3步:引入(使用)—— 在modules目录下创建一个名为main.js的入口文件,用于打包时设置entry属性
// 第一步:require,引入/使用/加载(一个包)。这里的模块名是hello,不用在后面加.js。就像java中import类时,不会有.java结尾。 var hello = require("./hello"); // 第二步:调用方法 hello.sayHi(); hello.sayHi1(); hello.sayHi2(); hello.sayHi3();
- 第4步:打包编码与设置 —— 在项目目录下创建webpack.config.js配置文件,使用webpack命令打包
// 前端一直在抄袭我们 模仿我们 // module.exports把这些模块(main.js、hello.js)编译》导出》打包 module.exports = {entry:"./modules/main.js", // 程序入口main.js。相当于java springboot程序的Application.java(入口程序)的那个main()方法output:{filename:"./js/bundle.js" // 输出到js目录(自动生成)下的bundle.js(自动生成)} }
- 第5步:打包操作完成 —— vscode终端中输入打包命令"webpack":
- bundle.js:经过编译(es6 》es5)、打包、压缩。
- 第6步:使用index.html —— 我们编写的代码(hello.js、main.js)经过打包出来能用了(bundle.js),我们在index.html中使用一下:
<!DOCTYPE html> <html><head><meta charset="UTF-8"><title>狂神说Java</title><!-- 导入编译、打包完成的bundle.js,并使用 --></head><body><!-- 这就是前端的模块化开发 --><script src="dist/js/bundle.js"></script></body> </html>
- 狂神文档参考:
十八 vue-router路由(转发)
- 业务
- 在讲完webpack(exports、require)以后,大家就能够看懂vue的工程了。
- vue遵循的是soc原则,vue本身只关注视图层,而vue工程中路由(即多个页面跳转,即以后我们后端中的重定向、转发的事情将由前端来做)的功能是使用vue-router路由组件(vue自带的)来实现的。
- 需求:多个页面之间的跳转(后端的重定向、转发事情将由前端来做)
- 思想路
- Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。这句话的意思是,我们可以直接使用vue-router,直接import即可。
- 包含的功能有:
- 嵌套的路由/视图表 —— 也就是说,从vue的角度来看,一个页面是很多很多的组件 + 很多插槽组成(相当于html时期,一个一个div的嵌套)的。不同的页面中,只有一部分的组件的内容是变化的,此时我们可以把这一部分的组件路由到另一个组件,用另一个组件来代替它,再完成内容的渲染就行了。
- 模块化的、基于组件的路由配置 ——
- 路由参数、查询、通配符 ——
- 基于 Vue.js 过渡系统的视图过渡效果 ——
- 细粒度的导航控制 ——
- 带有自动激活的 CSS class 的链接 ——
- HTML5 历史模式或 hash 模式,在 IE9 中自动降级 ——
- 自定义的滚动条行为 ——
- 环境搭建 & 依赖(如axios、vue-router)的安装、导入、使用
- 第一步:新建vue工程(把src目录下多余的东西都删除掉),整理后得到的基础工程:
// main.jsimport Vue from 'vue' // 从vue那个组件里面,给它导过来 import App from './App' // 导入app组件Vue.config.productionTip = falsenew Vue({el: '#app',components: { App },template: '<App/>' })
// app.vue<template><div id="app"></div> </template><script>export default {name: 'App',components: {} } </script><style> #app {font-family: 'Avenir', Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px; } </style>
第二步:安装 —— vue-router(安装的原理,即把模块放到node_modules目录下。这相当于在java的项目中,把第三方的jar包放到lib目录下一样)
第1步:管理员运行cmd
第2步:cd到此项目根目录下
第3步:执行npm install vue-router --save-dev命令
报错:peer vue@"^3.2.0" from vue-router@4.1.2
第三步:详解 —— 安装后的vue-router,在“node_modules”目录下找,如下图所示:
从目录结构可以看出vue-router是一个标准的前端工程。
第四步:导入 —— 安装完成后,如果需要在App.vue中使用vue-router组件,那么就直接使用import关键字导入即可(相当于java中用import导入某个类),如下图所示:
第五步:显示声明使用 —— 上面只是把vue-router导入进来,但vue中需要显示地声明。
// main.jsimport Vue from 'vue' // 从vue那个组件里面,给它导过来 import App from './App' // 导入app组件 import VueRouter from 'vue-router' // 从安装的vue-router模块中导进来// from 'vue-router'是导入进来前的名字// import VueRouter是导入进来后使用的qkpbVue.config.productionTip = false// 显示地声明使用vue-router,使用的名字是导入进来后的名字 Vue.use(VueRouter);new Vue({el: '#app',components: { App },template: '<App/>' })
- 自定义组件的编写、导出、导入、使用(演示使用的项目的项目结构如下图)
- 第一步:编写&导出:在components目录下存放我们自己编写的组件Content.vue:
<!-- 组件的组成部分 --> <!-- 第一部分:页面 --> <template><div><h1>内容页</h1></div> </template><!-- 第二部分:一般是vue对象的一些东西,一般使用export进行导出 --> <script>export default {name: "Content"} </script><!-- 第三部分:页面样式 --> <style></style>
- 第二步:导入&使用:在App.vue中使用:
<template><div id="app"></div> </template><script> // 第一步:先导入 import Content from "./components/Content.vue" export default {name: 'App',components: {// 第二步:再使用Content} } </script><style> #app {font-family: 'Avenir', Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px; } </style>
- 第一步:编写&导出:在components目录下存放我们自己编写的组件Content.vue:
- 使用vue-router实现路由(重定向、转发)
- 第一步:编写&导出:在components目录下存放我们自己编写的组件Main.vue 和 Content.vue :
<template><div><h1>首页</h1></div> </template> <script>export default {name: "Main"} </script> <style></style>
<!-- 组件的组成部分 --> <!-- 第一部分:页面 --> <template><div><h1>内容页</h1></div> </template><!-- 第二部分:一般是vue对象的一些东西,一般使用export进行导出 --> <script>export default {name: "Content"} </script><!-- 第三部分:页面样式 --> <style></style>
- 第二步:在src目录下创建一个router文件夹,专门用于放在关于路由的东西
- 第三步:配置路由 —— 在router文件夹下面,创建路由的主配置文件index.js,专门用于编写路由规则:
// 导入vue import Vue from 'vue' // 导入路由插件 import Router from 'vue-router' // 导入上面定义的组件 import Content from '../components/Content' import Main from '../components/Main' // 显示声明使用路由 Vue.use(Router);// 导出新配置的路由 export default new Router({routes: [{// 路由路径,即只要你在浏览器地址栏输入的路径是“/content”,表明就要使用些路由。// 使用哪个路由 & 跳转到哪个组件,由name和component属性决定path: '/content',// 路由名称name: 'content',// 跳转到哪个组件component: Content},{//如何配置两个路由(假如 首页)path: '/main',name: 'main',component: Main}] });
从上面的代码可以看出,vue-router相当于我们java的什么呀?相当于我们springmvc项目controller类中的@RquestMapping注解,RquestMapping本身的作用就是接收前端的一个请求,并指定要方法处理的一些数据,最后要求方法跳转到另一个页面。vue-router其实也是干这么一个事情。
第四步:起用路由 —— 在前端工程的入口程序main.js中配置:
import Vue from 'vue' import App from './App' // 第一步:导入上面创建的路由主配置文件所在的目录,并且取名为“router” import router from './router' Vue.config.productionTip = false new Vue({el: '#app',// 第二步:使用(配置的)路由(表),vue会自动扫描里面的路由配置router,components: { App },template: '<App/>' })
第五步:演示路由功能 —— 在 App.vue 中使用路由:
<template><div id="app"><!--router-link: 默认会被渲染成一个 <a> 标签,to 属性为指定链接router-view: 用于渲染路由匹配到的组件--><router-link to="/main">首页</router-link><router-link to="/content">内容</router-link><router-view></router-view></div> </template><script> export default {name: 'App' } </script><style> </style>
第六步:验证
第1步:npm run dev 访问
第2步:点击可以跳转
- 第一步:编写&导出:在components目录下存放我们自己编写的组件Main.vue 和 Content.vue :
十九 vue + elementui
- 业务
- vue前端工程现在没有自己好看的页面,我们可以使用vue+elementui构建比较好看的页面。
- 需求:网站快速成型工具
- 解决方案:
- vue + elementui
- 推荐使用 npm 的方式安装,它能更好地和 webpack 打包工具配合使用。
- element-ui官网解读:组件 | Element
- element-ui的这些组件用起来和bootstrap的组件是一样的。
- 建议学习“element-ui(组件化开发,桌面化应用) + layui(弹窗)”用于代替“bootstrap(样式化开发,桌面化应用) + layui(弹窗)”。
- hellowor:vue + elementui
- 第一步:环境搭建 & 初始化项目
- 第一次创建项目
- 第1步:npm install vue-cli -g,全局安装vue脚手架
- 第二次创建项目
- 第1步:cmd管理员
- 第2步:cd来到工作空间
- 第3步:vue init webpack hello-vue,初始化一个webpack项目,项目名称是hello-vue:
- 第一次创建项目
- 第二步:安装各种插件和组件
- 第1步:准备
- 进入工程目录(cmd 管理员身份):cd hello-vue
- 第2步:安装vue-router
- npm install vue-router --save-dev
- peer vue@"^3.2.0" from vue-router@4.1.6 》npm i vue-router@3
- 第3步:安装element-ui
- npm i element-ui -s
- 第4步:安装所有的依赖
- npm install
- 第5步:安装SASS加载器
- cnpm方式
- cnpm install sass-loader node-sass --save-dev
- 这句命令安装了两个,一个是sass-loader,另一个是node-sass。
- 你们可以拆成两名命令,也可以合成一句命令,也就是说你要安装多个组件可以一句命令安装完。
- 这里使用cnpm的时候,是因为老师使用npm安装时失败了。淘宝的镜像再怎么着都比国外(npm)的快。
- 业务/需求:我们之前聊过,前端的一些东西不能用纯css来写,是不是它就用SASS呀,你要通过SASS去编辑生成啊。就是css嘛,使用SASS编辑生成css。
- Error: Cannot find module ‘diagnostics_channel,cnpm的版本过高 》npm uninstall -g cnpm 》npm install cnpm@7.1.0 -g 》cnpm install sass-loader node-sass --save-dev
- cnpm install sass-loader node-sass --save-dev
- npm方式
- peer webpack@"^5.0.0" from sass-loader@13.2.0 》npm i sass-loader@7
- node-sass pip 安装报错,提示缺少python2 (shuzhiduo.com) 》npm install node-sass@6
- cnpm方式
- 第6步:测试
- npm run dev
- 第1步:准备
- 第三步:编号开发
- 第1步:整理项目
- 第(1)步:使用vs code打开项目
- 第(2)步:删除src下默认的文件:assets/logo.png(默认的图片)、components/HelloWorld.vue(默认的组件)
- 第(3)步:整理src/App.vue
<template><div id="app"></div> </template><script> export default {name: 'App', } </script><style> #app {font-family: 'Avenir', Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px; } </style>
- 第(4)步:静态资源文件放在static吧,放在其它地方不可见啊
- 第(5)步:新建src/router目录,用于放路由
- 第(6)步:新建src/views目录,用于放置视图,也可以叫视图组件(视图也是组件的一部分,但分得细一点,视图一般用于交互的)。这里的views目录用于存放视图组件,而components目录用于存放功能性组件,这样分工是不是就更加明确了。
- 第3步:编码
- 第(1)步:在views目录下创建Main.vue视图
<template><h1>首页</h1> </template><script> export default {name: 'Main', } </script><style> </style>
- 第(2)步:在views目录下创建Login.vue视图(直接去ElementUI官网中拿的,不是我自己写的)。
<template><div><!-- el开头的就是element的组件(这里是表单) --><el-form ref="loginForm" :model="form" :rules="rules" label-width="80px" class="login-box"><h3 class="login-title">欢迎登录</h3><el-form-item label="账号" prop="username"><el-input type="text" placeholder="请输入账号" v-model="form.username"/></el-form-item><el-form-item label="密码" prop="password"><el-input type="password" placeholder="请输入密码" v-model="form.password"/></el-form-item><el-form-item><!--登录按钮,绑定了click事件,调用onSubmit方法--><el-button type="primary" v-on:click="onSubmit('loginForm')">登录</el-button></el-form-item></el-form><!--这里是一个提示框,即如果我们输入错误,就会弹窗--><el-dialogtitle="温馨提示":visible.sync="dialogVisible"width="30%":before-close="handleClose"><span>请输入账号和密码</span><span slot="footer" class="dialog-footer"> <el-button type="primary" @click="dialogVisible = false">确 定</el-button> </span></el-dialog></div> </template><script>export default {name: 'Login',data(){return{form:{username:'',password:''},// 表彰验证,需要在el-form-item元素中增加prop属性rules:{username:[{required:true,message:'账号不可为空',trigger:'blur'}],password:[{required:true,message:'密码不可为空',trigger:'blur'}]},// 对话框显示和隐藏dialogVisible:false}},methods:{onSubmit(formName) {// 为表单绑定验证功能this.$refs[formName].validate((valid) => {if(valid){// 使用vue-router路由到指定页面,该方式称之为编程式导航this.$router.push("/main");}else{this.dialogVisible = true;return false;}})}}} </script><style scoped>.login-box{border: 1px solid #DCDFE6;width: 350px;margin: 108px auto;padding: 35px 35px 15px 35px;border-radius: 5px;-webkit-border-radius:5px;-moz-border-radius:5px;box-shadow: 0 0 25px #909339;}.login-title{text-align: center;margin: 0 auto 40px auto;color: #303133;} </style>
第(3)步:路由index.js(那这个登录表单想要用怎么办?是不是要配置到路由里面去呀。组件写完它是独立的吧,独立的东西就要通过路由把它们交互起来)。
//第一步:引入(导入) import Vue from 'vue' import Router from 'vue-router' // 其中名称Router可以随便取,只要后面的vue-router对即可 import Main from '../views/Main' // 导入Main组件 import Login from '../views/Login'// 导入Login组件//第二步:显示地使用它 Vue.use(Router)//第三步:导出一个接口 export default new Router({routes:[// 放置(配置)各种各样的路由{path:'/main',// 请求链接component:Main// 路由(转发)到此组件},{path:'/login',// 请求链接component:Login// 路由(转发)到此组件}] });
第(4)步:main.js。路由配置到哪里去?配置到main.js里面去吧。
import Vue from 'vue' import App from './App' //第一步:要想使用路由,那就让路由去扫描相应的包(router目录)吧,这样子的话它就会把所有配置好的路由给加载进来 import router from './router' //第二步:elementui还没导入,我们是不是要把它导入进来呀。名字'element-ui'去哪里找呀?是不是去node_modules里面找呀 import Element from 'element-ui' //第三步:导入elementui对应的css。官网案例拷贝。 //说明它导入了一个css吧,是不是就需要SASS编辑器吧,这就是我们刚才导入SASS的原因。 import 'element-ui/lib/theme-chalk/index.css';//第四步:安装路由(显示地使用路由) Vue.use(router); //第五步:安装ElementUI(显示地使用ElementUI) Vue.use(ElementUI);//第六步:配置Router和ElementUI new Vue({el: '#app',router,// 配置router。render: h => h(App)// 配置ElementUI。官网拷贝。 })
第(5)步:App.vue修改:
<template><div id="app"><router-link to='/login'>login</router-link><router-link to='/main'>main</router-link><!--剩下的就是把路由到页面展示出来就好了--><router-view></router-view></div> </template><script> export default {name: 'App' } </script><style> </style>
- 第(1)步:在views目录下创建Main.vue视图
第3步:测试
npm run dev
附:排错,SASS版本过高
第(1)步:来到包版本管理文件pack.json,它里面有所有组件(插件)的版本吧。在里面找到SASS loader,看到是8.0.0版本的,所以版本太高了,所以这里我们把它的版本号改成7.3.1的版本。
第(2)步:由于pack.json中修改了版本,所以在终端重新npm install一下。npm install才是安装它吧,你改了不重新安装没有用的。
- 第1步:整理项目
- 第一步:环境搭建 & 初始化项目
二十 嵌套路由
- 业务与需求
- 如上图所示,有两个请求,外面都是一样。
- 左边那个图表明,如果我请求User下面的profile,它会显示profiel的内容。
- 右边那个图表明,如果我请求User下面的posts,它会显示posts的内容。
- 但是其它页面是不变的,这里它只变局部吧。只变局部,对于vue来说真的是太轻松了,对不对。为什么会轻松呀?因为vue是component组件拔插,对不对,意思就是说把这个组件放进去就可以了。 在vue中可以通过路由去实现这样的功能。
- 如上图所示,有两个请求,外面都是一样。
- 案例演示------------------------------------------------------------------------------
- 第一步:在src/views目录下创建user目录(模拟:用户管理模块)
- 第二步:在src/views/user目录下创建Profile.vue(模拟:用户管理模块中的,个人信息页面)。
<template><h1>个人信息Profile</h1> </template><script> export default {name: 'UserProfile' } </script><style> </style>
- 第三步:在src/views/user目录下创建List.vue(模拟:用户管理模块中的,用户列表页面)。
<template><h1>用户列表List</h1> </template><script> export default {name: 'UserList' } </script><style> </style>
- 第四步:src/views/Main.vue修改。关键是我们想把UserProfile.vue和UserList.vue展示出来吧。是不是应该展示在Main.vue(这里增加侧边栏)里面吧。
<template><div><el-container><el-aside width="200px"><el-menu :default-openeds="['1']"><el-submenu index="1"><template solt="title"><i class="el-icon-caret-right"></i>用户管理</template><el-menu-item-group><el-menu-item index="1-1"><!-- 通过router-link把用户个人信息放进去 --><router-link to="/user/profile">个人信息</router-link></el-menu-item><el-menu-item index="1-2"><!-- 通过router-link把用户列表放进去 --><router-link to="/user/list">用户列表</router-link></el-menu-item></el-menu-item-group></el-submenu><el-submenu index="2"><template solt="title"><i class="el-icon-caret-right"></i>内容管理</template><el-menu-item-group><el-menu-item index="2-1">分类管理</el-menu-item><el-menu-item index="2-2">内容列表</el-menu-item></el-menu-item-group></el-submenu></el-menu></el-aside><el-container><el-header style="text-align: right; font-size: 12px"><el-dropdown><i class="el-icon-setting" style="margin-right:15px"></i><el-dropdown-menu slot="dropdown"><el-dropdown-item>个人信息</el-dropdown-item><el-dropdown-item>退出登录</el-dropdown-item></el-dropdown-menu></el-dropdown></el-header><el-main><!-- 它会把主页的东西展示在这里 --><!-- 即上面的两个router-link吧。 --><!-- 总结:一个页面中肯定有一个router-view,展示的内容是router-link指向的组件。 --><router-view/></el-main></el-container></el-container></div> </template><script>export default {name: "Main"} </script><style scoped lang="scss">.el-header {background-color: #048bd1;color: #333;line-height: 60px;}.el-aside {color: #333;} </style>
- 第五步:index.js。我们定义了3个组件,所以我们要把它导到路由组件里面去。
//第一步:引入(导入) import Vue from 'vue' import Router from 'vue-router' // 其中名称Router可以随便取,只要后面的vue-router对即可 import Main from '../views/Main' // 导入Main组件 import Login from '../views/Login'// 导入Login组件 import UserList from '../views/user/List' import UserProfile from '../views/user/Profile'//第二步:显示地使用它 Vue.use(Router)//第三步:导出一个接口 export default new Router({routes:[// 放置(配置)各种各样的路由{// 正常的(非嵌套)路由path:'/main',component:Main,// 嵌套路由children:[{path:'/user/profile',// 请求链接component:UserProfile// 路由(转发)到此组件},{path:'/user/list',// 请求链接component:UserList// 路由(转发)到此组件} ]},{path:'/login',component:Login}] });
- 第六步:测试
- npm run dev
- http://localhost:8080/
- 报错:<style scoped lang="scss">改成<style scoped>
二十一 参数传递及重定向
- 参数传递
- 业务
- 点击左侧导航栏的“个人信息”菜单,要求每个登录的人,展示不同的个人信息。
- 需求
- 第一步:接收前端的参数
- 第二步:请求的方式会是:localhost:8080/user/profile?userId=xxx
- 解决方案
- <router-link to>
- 案例:没有解偶:在你的组件中使用
$route
会与路由紧密耦合,这限制了组件的灵活性,因为它只能用于特定的 URL。虽然这不一定是件坏事,但我们可以通过props
配置来解除这种行为:- 传参 —— 组件,Main.vue
<template><div><el-container><el-aside width="200px"><el-menu :default-openeds="['1']"><el-submenu index="1"><template solt="title"><i class="el-icon-caret-right"></i>用户管理</template><el-menu-item-group><el-menu-item index="1-1"><!-- 不传参 --><!--<router-link to="/user/profile">个人信息</router-link>--><!-- 传参:name传递的是路由名称,params传递的是组件参数列表 --><router-link :to="{name:'UserProfile',params:{id:1}}">个人信息</router-link></el-menu-item><el-menu-item index="1-2"><router-link to="/user/list">用户列表</router-link></el-menu-item></el-menu-item-group></el-submenu><el-submenu index="2"><template solt="title"><i class="el-icon-caret-right"></i>内容管理</template><el-menu-item-group><el-menu-item index="2-1">分类管理</el-menu-item><el-menu-item index="2-2">内容列表</el-menu-item></el-menu-item-group></el-submenu></el-menu></el-aside><el-container><el-header style="text-align: right; font-size: 12px"><el-dropdown><i class="el-icon-setting" style="margin-right:15px"></i><el-dropdown-menu slot="dropdown"><el-dropdown-item>个人信息</el-dropdown-item><el-dropdown-item>退出登录</el-dropdown-item></el-dropdown-menu></el-dropdown></el-header><el-main><router-view/></el-main></el-container></el-container></div> </template><script>export default {name: "Main"} </script><style scoped lang="scss">.el-header {background-color: #048bd1;color: #333;line-height: 60px;}.el-aside {color: #333;} </style>
接收参数 —— 路由,index.js
import Vue from 'vue' import Router from 'vue-router' import Main from '../views/Main' import Login from '../views/Login' import UserList from '../views/user/List' import UserProfile from '../views/user/Profile'Vue.use(Router)export default new Router({routes:[{path:'/main',component:Main,// 嵌套路由children:[{ // 其中的"/:id"用于接收参数path:'/user/profile/:id',name:"UserProfile",//“路由名称”用于<router-link>中的to属性用于传参数component:UserProfile},{path:'/user/list',component:UserList} ]},{path:'/login',component:Login}] });
页面展示“传递的参数” —— Profile.vue
<template><div><h1>个人信息Profile</h1><!-- 获取参数(展示) -->{{$route.params.id}}</div> </template><script> export default {name: 'UserProfile' } </script><style> </style>
测试成功
Module build failed Error Node Sass version 6.0.0 is incompatible with ^4.0.0
"{{$route.params.id}}" outside root element will be ignored.
- 传参 —— 组件,Main.vue
- 案例2:解偶(官网):通过
props
配置实现参数传递- 狂神案例
- 传参 —— Main.vue不变,<router-link :to="{name:'UserProfile',params:{id:1}}">个人信息</router-link>
- 接收 —— index.js,声明使用props的方式
import Vue from 'vue' import Router from 'vue-router' import Main from '../views/Main' import Login from '../views/Login' import UserList from '../views/user/List' import UserProfile from '../views/user/Profile'Vue.use(Router)export default new Router({routes:[{path:'/main',component:Main,children:[{ path:'/user/profile/:id',name:"UserProfile",props: true, // props参数传递,解偶component:UserProfile},{path:'/user/list',component:UserList}]},{path:'/login',component:Login}] });
- 页面展示“传递的参数” —— Profile.vue,通过组件去接收参数
<template><div><h1>个人信息Profile</h1><!-- // props参数传递,解偶 -->{{id}}abc</div> </template><script> export default {// props参数传递,解偶,使用组件的方式接收参数props:['id'],name: 'UserProfile' } </script><style> </style>
- 官方文档
- 我们可以将下面的代码
const User = {template: '<div>User {{ $route.params.id }}</div>' } const routes = [{ path: '/user/:id', component: User }]
替换成
const User = {// 请确保添加一个与路由参数完全相同的 prop 名props: ['id'],template: '<div>User {{ id }}</div>' } const routes = [{ path: '/user/:id', component: User, props: true }]
- 我们可以将下面的代码
- 狂神案例
总结:
在正常情况下,我们应该是传递一个对象,用对象作为参数吧。现在我们学会了单个参数(userId)的传递,那么同理,传递一个(甚至多个)对象也是用同样的方法,以此类推罢了。
- 业务
- 重定向
- 怎么能够实现重定向呢?
- 浏览器地址栏url不变的跳转,叫做转发。浏览器地址栏url变化的跳转,叫重定向。
- 重定向的意思就是从一个path,跳转到另外一个path。
- 案例
- 第一步:index.js,修改路由配置文件
import Vue from 'vue' import Router from 'vue-router' import Main from '../views/Main' import Login from '../views/Login' import UserList from '../views/user/List' import UserProfile from '../views/user/Profile'Vue.use(Router)export default new Router({routes:[{path:'/main',component:Main,children:[{ path:'/user/profile/:id',name:"UserProfile",},{path:'/user/list',component:UserList},{path:'/goHome',// 重定向,第一步:redirect:'/main'redirect:'/main'} ]},{path:'/login',component:Login}] });
- 第二步:Main.vue,修改
<template><div><el-container><el-aside width="200px"><el-menu :default-openeds="['1']"><el-submenu index="1"><template solt="title"><i class="el-icon-caret-right"></i>用户管理</template><el-menu-item-group><el-menu-item index="1-1"><router-link to="/user/profile">个人信息</router-link></el-menu-item><el-menu-item index="1-2"><router-link to="/user/list">用户列表</router-link></el-menu-item><!-- 第二步:传参 --><el-menu-item index="1-3"><router-link to="/goHome">返回首页</router-link></el-menu-item></el-menu-item-group></el-submenu><el-submenu index="2"><template solt="title"><i class="el-icon-caret-right"></i>内容管理</template><el-menu-item-group><el-menu-item index="2-1">分类管理</el-menu-item><el-menu-item index="2-2">内容列表</el-menu-item></el-menu-item-group></el-submenu></el-menu></el-aside><el-container><el-header style="text-align: right; font-size: 12px"><el-dropdown><i class="el-icon-setting" style="margin-right:15px"></i><el-dropdown-menu slot="dropdown"><el-dropdown-item>个人信息</el-dropdown-item><el-dropdown-item>退出登录</el-dropdown-item></el-dropdown-menu></el-dropdown></el-header><el-main><router-view/></el-main></el-container></el-container></div> </template><script>export default {name: "Main"} </script><style scoped lang="scss">.el-header {background-color: #048bd1;color: #333;line-height: 60px;}.el-aside {color: #333;} </style>
- 第一步:index.js,修改路由配置文件
- 怎么能够实现重定向呢?
二十二 404和路由钩子
- 业务需求1:
- 情况:在登录页面中输入什么样的用户名和密码都可以跳转到主页。
- 想要的:跳转到主页以后,应该显示当前登录人的信息。
- 案例:跳转到主页以后,应该显示当前登录人的信息。
- 传参:Login.vue
<template><div><el-form ref="loginForm" :model="form" :rules="rules" label-width="80px" class="login-box"><h3 class="login-title">欢迎登录</h3><el-form-item label="账号" prop="username"><el-input type="text" placeholder="请输入账号" v-model="form.username"/></el-form-item><el-form-item label="密码" prop="password"><el-input type="password" placeholder="请输入密码" v-model="form.password"/></el-form-item><el-form-item><el-button type="primary" v-on:click="onSubmit('loginForm')">登录</el-button></el-form-item></el-form><el-dialogtitle="温馨提示":visible.sync="dialogVisible"width="30%":before-close="handleClose"><span>请输入账号和密码</span><span slot="footer" class="dialog-footer"> <el-button type="primary" @click="dialogVisible = false">确 定</el-button> </span></el-dialog></div> </template><script>export default {name: 'Login',data(){return{form:{username:'',password:''},rules:{username:[{required:true,message:'账号不可为空',trigger:'blur'}],password:[{required:true,message:'密码不可为空',trigger:'blur'}]},dialogVisible:false}},methods:{onSubmit(formName) {this.$refs[formName].validate((valid) => {if(valid){// 跳转到主页以后,应该显示当前登录人的信息。// 第一步:传参this.$router.push("/main/"+this.form.username);}else{this.dialogVisible = true;return false;}})}}} </script><style scoped>.login-box{border: 1px solid #DCDFE6;width: 350px;margin: 108px auto;padding: 35px 35px 15px 35px;border-radius: 5px;-webkit-border-radius:5px;-moz-border-radius:5px;box-shadow: 0 0 25px #909339;}.login-title{text-align: center;margin: 0 auto 40px auto;color: #303133;} </style>
接收参数:index.js
import Vue from 'vue' import Router from 'vue-router' import Main from '../views/Main' import Login from '../views/Login' import UserList from '../views/user/List' import UserProfile from '../views/user/Profile'Vue.use(Router)export default new Router({routes:[{// 跳转到主页以后,应该显示当前登录人的信息。// 第二步:接收参数path:'/main/:name',component:Main,// 第三步:获取并展示参数// 第3-1步:声明使用props方式接收参数props:true,children:[{ path:'/user/profile/:id',name:"UserProfile",props: true, component:UserProfile},{path:'/user/list',component:UserList}]},{path:'/login',component:Login}] });
- 获取数据并展示:Main.vue
<template><div><el-container><el-aside width="200px"><el-menu :default-openeds="['1']"><el-submenu index="1"><template solt="title"><i class="el-icon-caret-right"></i>用户管理</template><el-menu-item-group><el-menu-item index="1-1"><router-link :to="{name: 'UserProfile',params: {id: 1}}">个人信息</router-link></el-menu-item><el-menu-item index="1-2"><router-link to="/user/list">用户列表</router-link></el-menu-item><el-menu-item index="1-3"><router-link to="/goHome">返回首页</router-link></el-menu-item></el-menu-item-group></el-submenu><el-submenu index="2"><template solt="title"><i class="el-icon-caret-right"></i>内容管理</template><el-menu-item-group><el-menu-item index="2-1">分类管理</el-menu-item><el-menu-item index="2-2">内容列表</el-menu-item></el-menu-item-group></el-submenu></el-menu></el-aside><el-container><el-header style="text-align: right; font-size: 12px"><el-dropdown><i class="el-icon-setting" style="margin-right:15px"></i><el-dropdown-menu slot="dropdown"><el-dropdown-item>个人信息</el-dropdown-item><el-dropdown-item>退出登录</el-dropdown-item></el-dropdown-menu></el-dropdown><!-- 第三步:获取并展示参数 --><!-- 第3-3步:获取并展示数据 --><span>{{name}}</span></el-header><el-main><router-view/></el-main></el-container></el-container></div> </template><script>export default {// 第三步:获取并展示参数// 第3-2步:使用props属性接收参数props:['name'],name: "Main"} </script><style scoped lang="scss">.el-header {background-color: #048bd1;color: #333;line-height: 60px;}.el-aside {color: #333;} </style>
测试
http://localhost:8080/
- 传参:Login.vue
业务需求2:去掉链接中的" # "
解决方案 —— 路由模式与404:
配置过程
第一步:index.js路由管理器
import Vue from 'vue' import Router from 'vue-router' import Main from '../views/Main' import Login from '../views/Login' import UserList from '../views/user/List' import UserProfile from '../views/user/Profile'Vue.use(Router)export default new Router({// 去掉链接中的" # ",history模式mode:'history',routes:[{path:'/main/:name',component:Main,props:true,children:[{ path:'/user/profile/:id',name:"UserProfile",props: true, component:UserProfile},{path:'/user/list',component:UserList}]},{path:'/login',component:Login}] });
第二步:测试
业务需求3:纯前端处理404
第一步:NotFound.vue,在src/views目录下创建新组件
<template><div id="app"><h1>大兄弟404了</h1></div> </template><script> export default {name: 'NotFound' } </script><style> </style>
第二步:index.js,写完组件第一种事情就是把组件配置到路由上去
import Vue from 'vue' import Router from 'vue-router' import Main from '../views/Main' import Login from '../views/Login' import UserList from '../views/user/List' import UserProfile from '../views/user/Profile' // 第一步:导入进来 import NotFound from '../views/NotFound'Vue.use(Router)export default new Router({mode:'history',routes:[{path:'/main/:name',component:Main,props:true,children:[{ path:'/user/profile/:id',name:"UserProfile",props: true, component:UserProfile},{path:'/user/list',component:UserList}]},{path:'/login',component:Login},{// 第二步:配置404的路由path:'*', // 测试1:拦截除以上请求之外的任何所有请求component:NotFound}] });
第三步:测试
业务需求4:路由钩子与异步请求
beforeRouteEnter,就像咱们的过滤器(chain链)、拦截器一样,即进入这个路由之前要进行过滤一下。to、from、next,即从哪里来(相当于HttpRequest),到哪里去(相同于HttpResponse),往下一个走(相当于chain链)。
beforeRouteLeave,离开某个路由之前干什么事,即离开某个路由之前又过滤一便。
案例演示1:在钩子函数中使用异步请
- 第一步:安装axios和vue-axios组件(插件), npm install axios -s npm install vue-axios -s
第二步:main.js要导入axios、vue-axios,不然你安装的组件是无法使用的
import axios from 'axios';
import VueAxios from 'vue-axios'
完整代码:
import Vue from 'vue' import App from './App' import router from './router' import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css'; // 第一步:安装Axios , cnpm install axios -s // 第二步:main.js引用Axios // 第2-1步:引入 import axios from 'axios'; import VueAxios from 'vue-axios' // 第2-2步:声明使用 Vue.use(VueAxios,axios) Vue.use(router); Vue.use(ElementUI);new Vue({el: '#app',router,render: h => h(App) })
第三步:准备数据:只有我们的static目录下的文件是可以被访问到的,所以我们就把静态文件放入该目录下。
//静态数据存放的位置:static/mock/data.json
完整代码:
{"name":"狂神说java","url": "http://baidu.com","page": "1","isNonProfit":"true","address": {"street": "含光门","city":"陕西西安","country": "中国"},"links": [{"name": "B站","url": "https://www.bilibili.com/"},{"name": "4399","url": "https://www.4399.com/"},{"name": "百度","url": "https://www.baidu.com/"}]}
第四步:Profile.vue:在beforeRouteEnter中进行异步请求
<template><div><h1>个人信息Profile</h1>{{id}}abc</div> </template><script> export default {props:['id'],name: 'UserProfile',// 路由钩子与异步请求// 进入这个页面之前,先执行这段代码,使用axios加载数据beforeRouteEnter:(to,from,next)=>{console.log("进入路由之前,使用axios加载数据");next((vm)=>{//vm —— 可以直接获取到当前的对象实例。vm就可以调用它本身methods中定义的方法。vm.getData();})//next();// 如果没有这句放,就阻塞了。//next("/path") //跳转到指定路径//next(false) //返回上一页}, // 离开这个页面之前,先执行这段代码。beforeRouteLeave:(to,from,next)=>{console.log("离开路由之前纟xx");next();// 如果没有这句放,就阻塞了。},methods:{getData:function(){//使用axios加载数据this.axios({//请求method:'get',//get方式url:'http://localhost:8080/static/mock/data.json'}).then(function(response){//response是响应的东西,响应回来的结果console.log(response);});}} } </script><style> </style>
第五步:测试
直接访问data.json:localhost:8080/static/mock/data.json
访问主页:localhost:8080/main
访问个人信息页面:http://localhost:8080/user/profile/1
附1:docsify(一键)帮助文档生成工具
附2:npm命令解释
附3:最终项目的完整结构图
vue,狂神,狂神和飞哥,前端一直在抄袭后端相关推荐
- 前端大串讲,狂神,狂神和飞哥
-大前端进阶 - 篇章学习-Kuang-Study-文章 (377条消息) Vue入门技能树 (csdn.net) npm install -g npm@9.2.0 一 概述 前端框架:vue.Rea ...
- 支付宝支付 第十二集:狂神、飞哥支付宝支付配置代码(免费资源,拿走不谢)
支付宝支付 第十二集:狂神.飞哥支付宝支付配置代码(免费资源,拿走不谢) 一.资源 链接:https://pan.baidu.com/s/1S-VAAMxiaPkgb2XZMQYEjA 提取码:091 ...
- RabbitMQ狂神说笔记(RabbitMQ B站狂神说笔记、KuangStudy、学相伴飞哥)
一. 引用文章 RabbitMQ狂神说笔记(B站狂神说笔记.KuangStudy.学相伴飞哥) RabbitMQ狂神说笔记(B站狂神说笔记.KuangStudy.学相伴飞哥)百度云盘地址,提取码:07 ...
- 飞哥:程序员完全没时间提升自己该怎么办?
大家好,我是飞哥! 很多同学都和我说过一个问题,有心想扎实地提高技术能力,但无奈工作太忙没有时间该咋办.相信你的实际工作中可能也有过过类似的困境. 当你工作了以后,你会发现抽出时间来学习貌似是一件很困 ...
- element ui 前台模板_SpringBoot + Vue + ElementUI 实现后台管理系统模板 -- 前端篇(二):引入 element-ui 定义基本页面显示...
前提: (1) 相关博文地址: SpringBoot + Vue + ElementUI 实现后台管理系统模板 -- 前端篇(一):搭建基本环境:https://www.cnblogs.com/l-y ...
- vue学习笔记-01-前端的发展历史(从后端到前端,再到前后端分离,再到全栈)
vue学习笔记-01-前端的发展历史(从后端到前端,再到前后端分离,再到全栈) 这篇文章是博主在看vue-前端发展简史的时候做的笔记,以供后续学习复习 文章目录 vue学习笔记-01-前端的发展历 ...
- jpa 自定义sql if_跟飞哥学编程:SQL入门-:函数、存储过程和触发器
最后不要忘记:SQL是一种结构化(Structured)的语言(Language),所以它具有 编程语言的特性 声明变量和赋值 所谓变量,可以是看成一个存储数据的容器,所有它里面存储的值是可以变化的. ...
- Vue学习笔记(四)—— 前端路由
介绍 本文主要介绍路由的相关知识,当然主要是以Vue的路由为主要介绍对象. 有兴趣的朋友可以看看之前的文章: Vue学习笔记(一)-- 常用特性 Vue学习笔记(二)-- 组件开发 Vue学习笔记(三 ...
- sql找出2000-3000年中的闰年。_跟飞哥学编程:SQL入门-4-查询和条件
为了教学方便,我们先引入一个关键字: SELECT 使用SELECT,可以查询得到表数据,比如: SELECT 其中,星号(*)代表所有列.运行上述SQL语句,返回的就是Student表的所有行所有列 ...
最新文章
- 剑指offer:面试题16. 数值的整数次方
- 算法---删除排序链表中的重复元素 II
- 富文本编辑器 - wangEditor 表情
- java多参方法_Java中多参数方法进阶
- Mac忘记root密码(Mac OS Sierra忘记root密码如何重置)
- nsdictionary获取值_objective-c – 在NSDictionary中获取值
- JAVA深复制(深克隆)与浅复制(浅克隆)
- winxp制作服务器,你要知道的WinXP服务器操作系统安装的方法
- java byte数组与int,long,short,byte转换
- 全面规范的软件需求可以规避项目风险
- GB28181协议--心跳
- Apache ShenYu源码阅读系列-Divide插件
- IP地址分为几类?各如何表示?IP地址的主要特点是什么?
- Deep Learning for UAV-based Object Detection andTracking: A Survey(论文翻译)
- 集合 -- 如何安全删除 HashMap 中的元素
- picker多选 vant_浅谈vant组件Picker 选择器选单选问题
- PHP 图片上传 图片压缩
- 2022黑马Python学习笔记
- 二维码和条形码简单实现
- kali攻击wifi、破解wifi密码详细教程(二)