vue框架快速入门
vue
- 1、第一个Vue程序
- 1.1、什么是Vue程序
- 1.2、为什么要使用MVVM
- 1.3、Vue
- 1.4、第一个vue程序
- 2、基础语法
- 2.1、v-bind
- 2.2、v-if, v-else
- 2.3、v-for
- 2.4、v-on
- 3、Vue表单双绑、组件
- 3.1、什么是双向数据绑定
- 3.2、在表单中使用双向数据绑定
- 3.3、什么是组件
- 4、Axios异步通信
- 4.1、什么是Axios
- 4.2、第一个Axios应用程序
- 5、计算属性、内容分发、自定义事件
- 5.1、什么是计算属性
- 5.2、内容分发
- 5.3、自定义事件
- 5.4、Vue入门小结
- 6、第一个vue-cli项目
- 6.1、什么是vue-cli
- 6.2、需要的环境
- 6.3、第一个vue-cli应用程序
- 7、webpack使用
- 7.1、什么是Webpack
- 7.2、模块化的演进
- 7.3、安装Webpack
- 7.4使用webpack
- 8、vue-router路由
- 8.1、说明
- 8.2、安装
- 8.2、测试
- 9、实战快速上手
- 9.1、创建工程
- 9.2、创建登录页面
- 9.3、路由嵌套
- 9.4、参数传递
- 9.5、组件重定向
- 9.6、路由模式与 404
- 9.7、路由钩子与异步请求
1、第一个Vue程序
1.1、什么是Vue程序
MVVM(Model-View-ViewModel)是一种软件设计模式,由微软WPF(用于替代WinForm,以前就是用这个技术开发桌面应用程序的)和Silverlight(类似于Java Applet,简单点说就是在浏览器上运行WPF)的架构师Ken Cooper和Ted Peters开发,是一种简化用户界面的事件驱动编程方式。由John Gossman(同样也是WPF和Sliverlight的架构师)与2005年在他的博客上发表
MVVM源自于经典的MVC(Model-View-Controller)模式。MVVM的核心是ViewModel层,负责转换Model中的数据对象来让数据变得更容易管理和使用。其作用如下:
- 该层向上与视图层进行双向数据绑定
- 向下与Model层通过接口请求进行数据交互
MVVM已经相当成熟了,主要运用但不仅仅在网络应用程序开发中。当下流行的MVVM框架有Vue.js
,Anfular JS
1.2、为什么要使用MVVM
MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model),有几大好处
- 低耦合: 视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变
- 可复用: 你可以把一些视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑
- 独立开发: 开发人员可以专注于业务逻辑和数据的开发(ViewMode),设计人员可以专注于页面设计
- 可测试: 界面素来是比较难以测试的,而现在测试可以针对ViewModel来写
(1)View
View是视图层, 也就是用户界面。前端主要由HTH L和csS来构建, 为了更方便地展现vi eu to del或者Hodel层的数据, 已经产生了各种各样的前后端模板语言, 比如FreeMarker,Thyme leaf等等, 各大MV VM框架如Vue.js.Angular JS, EJS等也都有自己用来构建用户界面的内置模板语言。
(2)Model
Model是指数据模型, 泛指后端进行的各种业务逻辑处理和数据操控, 主要围绕数据库系统展开。这里的难点主要在于需要和前端约定统一的接口规则
(3)ViewModel
ViewModel是由前端开发人员组织生成和维护的视图数据层。在这一层, 前端开发者对从后端获取的Model数据进行转换处理, 做二次封装, 以生成符合View层使用预期的视图数据模型。
需要注意的是View Model所封装出来的数据模型包括视图的状态和行为两部分, 而Model层的数据模型是只包含状态的
- 比如页面的这一块展示什么,那一块展示什么这些都属于视图状态(展示)
- 页面加载进来时发生什么,点击这一块发生什么,这一块滚动时发生什么这些都属于视图行为(交互)
视图状态和行为都封装在了View Model里。这样的封装使得View Model可以完整地去描述View层。由于实现了双向绑定, View Model的内容会实时展现在View层, 这是激动人心的, 因为前端开发者再也不必低效又麻烦地通过操纵DOM去更新视图。
MVVM框架已经把最脏最累的一块做好了, 我们开发者只需要处理和维护View Model, 更新数据视图就会自动得到相应更新,真正实现事件驱动编程
。
View层展现的不是Model
层的数据, 而是ViewModel
的数据, 由ViewModel
负责与Model
层交互, 这就完全解耦了View层和Model层, 这个解耦是至关重要的, 它是前后端分离方案实施的重要一环。
1.3、Vue
Vue(读音/vju/, 类似于view) 是一套用于构建用户界面的渐进式框架, 发布于2014年2月。与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层, 不仅易于上手,还便于与第三方库(如:vue-router,vue-resource,vue x) 或既有项目整合
(1)MVVM模式的实现者
- Model:模型层, 在这里表示JavaScript对象
- View:视图层, 在这里表示DOM(HTML操作的元素)
- ViewModel:连接视图和数据的中间件, Vue.js就是MVVM中的ViewModel层的实现者
在MVVM架构中, 是不允许数据和视图直接通信的, 只能通过ViewModel来通信, 而View Model就是定义了一个Observer观察者
- ViewModel能够观察到数据的变化, 并对视图对应的内容进行更新
- ViewModel能够监听到视图的变化, 并能够通知数据发生改变
至此, 我们就明白了, Vue.js就是一个MV VM的实现者, 他的核心就是实现了DOM监听与数据绑定
(2)为什么要使用Vue.js
- 轻量级, 体积小是一个重要指标。Vue.js压缩后有只有20多kb(Angular压缩后56kb+,React压缩后44kb+)
- 移动优先。更适合移动端, 比如移动端的Touch事件
- 易上手,学习曲线平稳,文档齐全
- 吸取了Angular(模块化) 和React(虚拟DOM) 的长处, 并拥有自己独特的功能,如:计算属性
- 开源,社区活跃度高
1.4、第一个vue程序
【说明】IDEA可以安装Vue的插件!
注意:Vue不支持IE 8及以下版本, 因为Vue使用了IE 8无法模拟的ECMAScript 5特性。但它支持所有兼容ECMAScript 5的浏览器
(1)下载地址
- Vue.js
- CDN:
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
(2)代码编写
Vue.js的核心是实现了MVVM模式, 她扮演的角色就是View Model层, 那么所谓的第一个应用程序就是展示她的数据绑定功能,操作流程如下:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><!--view层--><div id="app">{{message}}</div><!--1.导入Vue.js--><script src="./static/vue.js"></script><script>var vm = new Vue({el: "#app",//Model : 数据data: {message: "hello,vue"}});</script></body>
</html>
- 说明:
el : "#vue"
:绑定元素的IDdata:{message : "Hello Vue!"}
:数据对象中有一个名为message的属性,并设置了初始值 Hello Vue!- 只需要在绑定的元素中使用
双花括号
将Vue创建的名为message属性包裹起来, 即可实现数据绑定功能, 也就实现了View Model层所需的效果
2、基础语法
2.1、v-bind
我们已经成功创建了第一个Vue应用!看起来这跟渲染一个字符串模板非常类似, 但是Vue在背后做了大量工作。现在数据和DOM已经被建立了关联, 所有东西都是响应式的。我们在控制台操作对象属性,界面可以实时更新!
我们还可以使用v-bind来绑定元素特性!
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>Title</title></head><body><!--view层--><div id="app"><span v-bind:title="message">鼠标悬停几秒查看此处动态绑定提示信息!</span></div><!--1.导入Vue.js--><script src="./static/vue.js"></script><script>var vm = new Vue({el: "#app",//Model : 数据data: {message: "页面加载于" + new Date().toLocaleString()}});</script></body>
</html>
你看到的v-bind等被称为指令。指令带有前缀v以表示它们是Vue提供的特殊特性。可能你已经猜到了, 它们会在渲染的DOM上应用特殊的响应式行为在这里,该指令的意思是:“将这个元素节点的title特性和Vue实例的message属性保持一致”。
2.2、v-if, v-else
什么是条件判断语句,以下两个属性
v-if
v-else
使用v-*属性绑定数据是不需要双花括号包裹的
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>Title</title></head><body><!--view层,模板--><div id="app"><h1 v-if="type==='A'">A</h1><h1 v-else-if="type==='B'">B</h1><h1 v-else="type">C</h1></div><!--1.导入Vue.js--><script src="./static/vue.js"></script><script type="text/javascript">var vm = new Vue({el: "#app",/*Model:数据*/data: {type: 'A'}});</script></body>
</html>
2.3、v-for
- v-for
items
是数组,item
是数组元素迭代的别名
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><!--view层,模板--><div id="app"><li v-for="item in items">{{item.message}}</li></div><!--1.导入Vue.js--><script src="./static/vue.js"></script><script type="text/javascript">var vm = new Vue({el:"#app",/*Model:数据*/data:{items:[{message:'Java学不会'},{message:'前端学不会'},{message:'运维学不会'}]}});</script></body>
</html>
2.4、v-on
v-on
监听事件
emsp;事件有Vue的事件、和前端页面本身的一些事件!我们这里的click
是vue的事件, 可以绑定到Vue中的methods
中的方法事件!
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>Title</title></head><body><div id="app"><button v-on:click="sayHi">点我</button></div><script src="./static/vue.js"></script><script type="text/javascript">var vm = new Vue({el:"#app",data:{message:'Hello World'},methods:{sayHi:function(event){//'this'在方法里面指向当前Vue实例alert(this.message);}}});</script></body>
</html>
3、Vue表单双绑、组件
3.1、什么是双向数据绑定
Vue.js是一个MV VM框架, 即数据双向绑定, 即当数据发生变化的时候, 视图也就发生变化, 当视图发生变化的时候,数据也会跟着同步变化。这也算是Vue.js的精髓之处了。
值得注意的是,我们所说的数据双向绑定,一定是对于UI控件来说的非UI控件不会涉及到数据双向绑定。单向数据绑定是使用状态管理工具的前提。如果我们使用vue x那么数据流也是单项的,这时就会和双向数据绑定有冲突。
- 为什么要实现数据的双向绑定:
在Vue.js
中,如果使用vuex
, 实际上数据还是单向的, 之所以说是数据双向绑定,这是用的UI控件来说, 对于我们处理表单, Vue.js的双向数据绑定用起来就特别舒服了。即两者并不互斥,在全局性数据流使用单项,方便跟踪;局部性数据流使用双向,简单易操作。
3.2、在表单中使用双向数据绑定
你可以用v-model
指令在表单<input>
、<textarea>
、及<select>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇, 但v-model本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
注意:v-model会忽略所有表单元素的value、checked、selected特性的初始值而总是将Vue实例的数据作为数据来源。你应该通过JavaScript在组件的data选项中声明初始值!
(1)单行文本
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>Title</title></head><body><!--view层--><div id="app">输入的文本:<input type="text" v-model="message">{{message}}</div><!--1.导入Vue.js--><script src="./static/vue.js"></script><script>var vm = new Vue({el: "#app",data: {message: null}});</script></body>
</html>
(2)多行文本
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>Title</title></head><body><!--view层--><div id="app"><textarea v-model="message" ></textarea>{{message}}</div><!--1.导入Vue.js--><script src="./static/vue.js"></script><script>var vm = new Vue({el: "#app",data: {message: null}});</script></body>
</html>
(3)单复选框
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>Title</title></head><body><!--view层--><div id="app">性别:<input type="radio" name="sex" value="男" v-model="checked">男<input type="radio" name="sex" value="女" v-model="checked">女<p>选中了:{{checked}}</p></div><!--1.导入Vue.js--><script src="./static/vue.js"></script><script>var vm = new Vue({el: "#app",data: {checked: null}});</script></body>
</html>
(4)下拉框
注意:v-model
表达式的初始值未能匹配任何选项,元系将被渲染为“未选中”状态。 在iOS中, 这会使用户无法选择第一个选项,因为这样的情况下,iOS不会触发change事件。因此,更推荐像上面这样提供一个值为空的禁用选项
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>Title</title></head><body><!--view层--><div id="app">下拉框:<select v-model="select"><option disabled value="">请选择</option><option>A</option><option>B</option><option>C</option></select><span>{{select}}</span></div><!--1.导入Vue.js--><script src="./static/vue.js"></script><script>var vm = new Vue({el: "#app",data: {select: ''}});</script></body>
</html>
3.3、什么是组件
组件是可复用的Vue
实例, 说白了就是一组可以重复使用的模板, 跟JSTL
的自定义标签、Thymeleal
的th:fragment
等框架有着异曲同工之妙,通常一个应用会以一棵嵌套的组件树的形式来组织:
例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件
(1)第一个Vue组件
注意:在实际开发中,我们并不会用以下方式开发组件,而是采用vue-cli
创建,vue
模板文件的方式开发,以下方法只是为了让大家理解什么是组件
使用Vue.component()
方法注册组件,格式如下:
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>Title</title></head><body><!--view层--><div id="app"><!--组件:传递给组件中的值:props--><java v-for="item in items" v-bind:study="item"></java></div><!--1.导入Vue.js--><script src="./static/vue.js"></script><script>//定义一个Vue组件componentVue.component("java", {props:['study'],template: '<li>{{study}}</li>'});var vm = new Vue({el: "#app",data: {items:["java","linux","html","css","js"]}});</script></body>
</html>
- 注意:
- 默认规则下props属性里的值不能为大写;
Vue.component()
:注册组件java
:自定义组件的名字template
:组件的模板v-for="item in items"
:遍历Vue
实例中定义的名为items
的数组,并创建同等数量的组件v-bind:study="item"
:将遍历的item
项绑定到组件中props
定义名为item
属性上;= 号左边的study
为props
定义的属性名,右边的为item in items
中遍历的item
项的值
4、Axios异步通信
4.1、什么是Axios
Axios是一个开源的可以用在浏览器端和Node JS
的异步通信框架, 她的主要作用就是实现AJAX异步通信,其功能特点如下:
- 从浏览器中创建
XMLHttpRequests
- 从node.js创建http请求
- 支持Promise API[JS中链式编程]
- 拦截请求和响应
- 转换请求数据和响应数据
- 取消请求
- 自动转换JSON数据
- 客户端支持防御XSRF(跨站请求伪造)
- GitHub
- 中文文档
为什么要使用Axios
- 由于
Vue.js
是一个视图层框架并且作者(尤雨溪) 严格准守SoC(关注度分离原则)所以Vue.js
并不包含AJAX的通信功能, 为了解决通信问题, 作者单独开发了一个名为vue-resource
的插件, 不过在进入2.0版本以后停止了对该插件的维护并推荐了Axios
框架。少用jQuery, 因为它操作Dom太频繁!
4.2、第一个Axios应用程序
咱们开发的接口大部分都是采用JSON格式, 可以先在项目里模拟一段JSON数据, 数据内容如下:创建一个名为data.json的文件并填入上面的内容, 放在项目的根目录下
{"name": "Java学不会","url": "https://i.csdn.net/#/user-center/profile?spm=1011.2124.3001.5111","page": 1,"isNonProfit": true,"address": {"street": "大沽南路","city": "天津河西","country": "中国"},"links": [{"name": "bilibili","url": "https://space.bilibili.com/95256449"},{"name": "Java学不会","url": "https://i.csdn.net/#/user-center/profile?spm=1011.2124.3001.5111"},{"name": "百度","url": "https://www.baidu.com/"}]
}
测试代码
<!DOCTYPE html>
<html lang="en" xmlns:v-binf="http://www.w3.org/1999/xhtml"><head><meta charset="UTF-8"><title>Title</title><!--解决闪烁问题--><style>[v-clock]{display: none;}</style></head><body><div id="vue" v-clock><div>{{info.name}}</div><div>{{info.address.city}}</div><a v-bind:href="info.url">点我</a></div><!--引入js文件--><script src="./static/vue.js"></script><script src="./static/axios.js"></script><script type="text/javascript">var vm = new Vue({el: "#vue",data(){return{//请求的返回参数格式,必须和json字符串一样info: {name: null,address: {street:null,city:null,county:null},url: null}}},mounted(){//钩子函数 链式编程 ES6新特性axios.get('../data.json').then(response=>(this.info=response.data))}});</script></body>
</html>
5、计算属性、内容分发、自定义事件
5.1、什么是计算属性
计算属性的重点突出在属性
两个字上(属性是名词),首先它是个属性
其次这个属性有计算
的能力(计算是动词),这里的计算就是个函数:简单点说,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性),仅此而已;可以想象为缓存!
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><!--view层--><div id="app"><p>currentTime1{{currentTime1()}}</p><p>currentTime2{{currentTime2}}</p></div><!--1.导入Vue.js--><script src="./static/vue.js"></script><script>var vm = new Vue({el: "#app",data: {message: "Hello,Java学不会"},methods: {currentTime1: function (){return Date.now(); //返回一个时间戳}},computed: { //计算属性currentTime2: function () {this.message;return Date.now(); //返回一个时间戳}}});</script></body>
</html>
注意:methods和computed里的东西不能重名
说明:
- methods:定义方法, 调用方法使用currentTime1(), 需要带括号
- computed:定义计算属性, 调用属性使用currentTime2, 不需要带括号:this.message是为了能够让currentTime2观察到数据变化而变化
- 如何在方法中的值发生了变化,则缓存就会刷新!可以在控制台使用
vm.message=”123"
, 改变下数据的值,再次测试观察效果!
结论:
调用方法时,每次都需要讲行计算,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?此时就可以考虑将这个结果缓存起来,采用计算属性可以很方便的做到这点,计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销;
5.2、内容分发
在
Vue.js
中我们使用<slot>
元素作为承载分发内容的出口,作者称其为插槽,可以应用在组合组件的场景中;
比如准备制作一个待办事项组件(todo) , 该组件由待办标题(todo-title) 和待办内容(todo-items)组成,但这三个组件又是相互独立的,该如何操作呢?
-
第一步定义一个待办事项的组件
<div id="app"><todo></todo> </div> <!--1.导入Vue.js--> <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script> <script type="text/javascript">Vue.component('todo',{template:'<div>\<div>代办事项</div>\<ul>\<li>学习Vue</li>\</ul>\</div>'}) </script>
-
第二步 我们需要让,代办事项的标题和值实现动态绑定,怎么做呢?
我们可以留一个插槽!
-
将上面的代码留出一个插槽,即slot
//slot:插槽 Vue.component("todo", {template:'<div>' +'<slot></slot>' +'<ul>' +'<slot></slot>' +'</ul>' +'</div>' });
-
定义一个名为todo-title的待办标题组件 和 todo-items的待办内容组件
Vue.component("todo-tile", {props: [`title`],template: '<p> {{title}}</p>' });Vue.component("todo-items", {props: ['item'],template: '<li> {{item}}</li>' });
-
实例化Vue并初始化数据
var vm = new Vue({el: "#app",data:{title: "Java学不会列表",todoItems:['Java学不会','前端学不会','Linux学不会']} });
-
将这些值,通过插槽插入
<div id="app"><todo><todo-tile slot="todo-tile" :title="title"></todo-tile><todo-items slot="todo-items" v-for="item in todoItems" :item="item"></todo-items></todo></div>
- 说明:我们的todo-title和todo-items组件分别被分发到了todo组件的todo-title和todo-items插槽中
- 完整代码
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><div id="app"><todo><todo-tile slot="todo-tile" :title="title"></todo-tile><todo-items slot="todo-items" v-for="item in todoItems" :item="item"></todo-items></todo></div><!--1.导入Vue.js--><script src="./static/vue.js"></script><script type="text/javascript">//slot:插槽Vue.component("todo", {template:'<div>' +'<slot name="todo-tile"></slot>' +'<ul>' +'<slot name="todo-items"></slot>' +'</ul>' +'</div>'});Vue.component("todo-tile", {props: [`title`],template: '<p> {{title}}</p>'});Vue.component("todo-items", {props: ['item'],template: '<li> {{item}}</li>'});var vm = new Vue({el: "#app",data:{title: "Java学不会列表",todoItems:['Java学不会','前端学不会','Linux学不会']}});</script></body> </html>
-
5.3、自定义事件
通以上代码不难发现,数据项在Vue的实例中, 但删除操作要在组件中完成, 那么组件如何才能删除Vue实例中的数据呢?此时就涉及到参数传递与事件分发了, Vue为我们提供了自定义事件的功能很好的帮助我们解决了这个问题; 使用this.$emit(‘自定义事件名’, 参数) , 操作过程如下:
-
在vue的实例中增加了methods对象并定义了一个名为removeTodoltems的方法
var vm = new Vue({el: "#app",data:{title: "Java学不会列表",todoItems:['Java学不会','前端学不会','Linux学不会']},methods:{removeItems: function (index){console.log("删除了"+this.todoItems[index]+"OK");//splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目,其中indexthis.todoItems.splice(index,1); //一次删除一个元素}}});
-
在vue的实例中增加了methods对象并定义了一个名为removeTodoltems的方法
Vue.component("todo-items", {props: ['item','index'],//只能绑定当前组件的方法template: '<li>{{index}}-------- {{item}}<button @click="remove">删除</button></li>',methods: {remove: function (index){//这里的remove是自定义事件名称,需要在HTML中使用v-on:remove的方式//this.$emit 自定义事件分发this.$emit('remove',index);}} });
-
修改todo-items待办内容组件的HTML代码,增加一个自定义事件,比如叫remove,可以和组件的方法绑定,然后绑定到vue的方法
<!--增加了v-on:remove="removeTodoItems(index)"自定义事件,该组件会调用Vue实例中定义的--> <todo-items slot="todo-items" v-for="(item,index) in todoItems":item="item" :index="index" v-on:remove="removeItems(index)"></todo-items>
-
对上一个代码进行修改,实现删除功能
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><title>Title</title></head><body><div id="app"><todo><todo-tile slot="todo-tile" :title="title"></todo-tile><!--增加了v-on:remove="removeTodoItems(index)"自定义事件,该组件会调用Vue实例中定义的--><todo-items slot="todo-items" v-for="(item,index) in todoItems":item="item" :index="index" v-on:remove="removeItems(index)"></todo-items></todo></div><!--1.导入Vue.js--><script src="./static/vue.js"></script><script type="text/javascript">//slot:插槽Vue.component("todo", {template:'<div>' +'<slot name="todo-tile"></slot>' +'<ul>' +'<slot name="todo-items"></slot>' +'</ul>' +'</div>'});Vue.component("todo-tile", {props: [`title`],template: '<p> {{title}}</p>'});Vue.component("todo-items", {props: ['item','index'],//只能绑定当前组件的方法template: '<li>{{index}}-------- {{item}}<button @click="remove">删除</button></li>',methods: {remove: function (index){//这里的remove是自定义事件名称,需要在HTML中使用v-on:remove的方式//this.$emit 自定义事件分发this.$emit('remove',index);}}});var vm = new Vue({el: "#app",data:{title: "Java学不会列表",todoItems:['Java学不会','前端学不会','Linux学不会']},methods:{removeItems: function (index){console.log("删除了"+this.todoItems[index]+"OK");//splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目,其中indexthis.todoItems.splice(index,1); //一次删除一个元素}}});</script></body> </html>
-
逻辑理解
5.4、Vue入门小结
核心:数据驱动,组件化
优点:借鉴了AngularJS的模块化开发和React的虚拟Dom,虚拟Dom就是把Demo操作放到内存中执行
常用的属性:
- v-if
- v-else-if
- v-else
- v-for
- v-on绑定事件,简写@
- v-model数据双向绑定
- v-bind给组件绑定参数,简写:
组件化:
- 组合组件slot插槽
- 组件内部绑定事件需要使用到
this.$emit("事件名",参数);
- 计算属性的特色,缓存计算数据
遵循SoC关注度分离原则,Vue是纯粹的视图框架,并不包含,比如Ajax之类的通信功能,为了解决通信问题,我们需要使用Axios框架做异步通信
说明: Vue的开发都是要基于NodeJS,实际开发采用Vue-cli脚手架开发,vue-router路由,vuex做状态管理;Vue UI,界面我们一般使用ElementUI(饿了么出品),或者ICE(阿里巴巴出品)来快速搭建前端项目~~
官网:
- ElementUI
- ICE
6、第一个vue-cli项目
6.1、什么是vue-cli
vue-cli官方提供的一个脚手架,用于快速生成一个vue的项目模板;
预先定义好的目录结构及基础代码,就好比咱们在创建Maven项目时可以选择创建一个骨架项目,这个估计项目就是脚手架,我们的开发更加的快速;
项目的功能
- 统一的目录结构
- 本地调试
- 热部署
- 单元测试
- 集成打包上线
6.2、需要的环境
- Node.js
- Git
- 镜像
- 确认nodejs安装成功:
-
cmd下输入
node -v
,查看是否能够正确打印出版本号即可 -
cmd下输入
npm -v
,查看是否能够正确打印出版本号即可
这个npm,就是一个软件包管理工具,就和linux下的apt软件安装差不多!
安装Node.js淘宝镜像加速器(cnpm)
这样的话,下载会快很多~# -g 就是全局安装 npm install cnpm -g# 或使用如下语句解决npm速度慢的问题 npm install --registry=https://registry.npm.taobao.org
安装的位置:C:\Users\administrator\AppData\Roaming\npm
- 安装vue-cli
cnpm install -g vue-cli #测试是否安装成功#查看可以基于哪些模板创建vue应用程序,通常我们选择webpack vue list
-
6.3、第一个vue-cli应用程序
-
创建一个Vue项目,我们随便建立一个空的文件夹在电脑上,我这里在E盘下新建一个目录
E:\Download\java\vue-first
-
创建一个基于webpack模板的vue应用程序
首先需要进入到对应的目录 cd E:\Download\java\vue-first 这里的myvue是顶日名称,可以根据自己的需求起名 vue init webpack myvue
-
说明:
- Project name:项目名称,默认回车即可
- Project description:项目描述,默认回车即可
- Author:项目作者,默认回车即可
- Install vue-router:是否安装vue-router,选择n不安装(后期需要再手动添加)
- Use ESLint to lint your code:是否使用ESLint做代码检查,选择n不安装(后期需要再手动添加)
- Set up unit tests:单元测试相关,选择n不安装(后期需要再手动添加)
- Setupe2etests with Nightwatch:单元测试相关,选择n不安装(后期需要再手动添加)
- Should we run npm install for you after the,project has been created:创建完成后直接初始化,选择n,我们手动执行;
- 运行结果:
-
初始化并运行
cd myvue //切换到项目目录 npm install //安装依赖 npm run dev //启动项目
- 执行完成后,目录多了很多依赖
- 当出现问题时,可以查看提示进行处理
7、webpack使用
7.1、什么是Webpack
本质上, webpack是一个现代JavaScript应用程序的静态模块打包器(module bundler) 。当webpack处理应用程序时, 它会递归地构建一个依赖关系图(dependency graph) , 其中包含应用程序需要的每个模块, 然后将所有这些模块打包成一个或多个bundle.
Webpack是当下最热门的前端资源模块化管理和打包工具, 它可以将许多松散耦合的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分离,等到实际需要时再异步加载。通过loader转换, 任何形式的资源都可以当做模块, 比如Commons JS、AMD、ES 6、CSS、JSON、Coffee Script、LESS等;
伴随着移动互联网的大潮, 当今越来越多的网站已经从网页模式进化到了WebApp模式。它们运行在现代浏览器里, 使用HTML 5、CSS 3、ES 6等新的技术来开发丰富的功能, 网页已经不仅仅是完成浏览器的基本需求; WebApp通常是一个SPA(单页面应用) , 每一个视图通过异步的方式加载,这导致页面初始化和使用过程中会加载越来越多的JS代码,这给前端的开发流程和资源组织带来了巨大挑战。
前端开发和其他开发工作的主要区别,首先是前端基于多语言、多层次的编码和组织工作,其次前端产品的交付是基于浏览器的,这些资源是通过增量加载的方式运行到浏览器端,如何在开发环境组织好这些碎片化的代码和资源,并且保证他们在浏览器端快速、优雅的加载和更新,就需要一个模块化系统,这个理想中的模块化系统是前端工程师多年来一直探索的难题。
7.2、模块化的演进
-
Script标签
<script src = "module1.js"></script> <script src = "module2.js"></script> <script src = "module3.js"></script>
- 这是最原始的JavaScript文件加载方式,如果把每一个文件看做是一个模块,那么他们的接口通常是暴露在全局作用域下,也就是定义在window对象中,不同模块的调用都是一个作用域
-
这种原始的加载方式暴露了一些显而易见的弊端:
- 全局作用域下容易造成变量冲突
- 文件只能按照
<script>
的书写顺序进行加载 - 开发人员必须主观解决模块和代码库的依赖关系
- 在大型项目中各种资源难以管理,长期积累的问题导致代码库混乱不堪
CommonsJS
服务器端的NodeJS遵循CommonsJS规范,该规范核心思想是允许模块通过require方法来同步加载所需依赖的其它模块,然后通过exports或module.exports来导出需要暴露的接口
require("module");
require("../module.js");
export.doStuff = function(){};
module.exports = someValue;
- 优点:
- 服务器端模块便于重用
- NPM中已经有超过45万个可以使用的模块包
- 简单易用
- 缺点:
- 同步的模块加载方式不适合在浏览器环境中,同步意味着阻塞加载,浏览器资源是异步加载的
- 不能非阻塞的并行加载多个模块
- 实现:
- 服务端的NodeJS
- Browserify,浏览器端的CommonsJS实现,可以使用NPM的模块,但是编译打包后的文件体积较大
- modules-webmake,类似Browserify,但不如Browserify灵活
- wreq,Browserify的前身
AMD
Asynchronous Module Definition规范其实主要一个主要接口define(id?,dependencies?,factory);它要在声明模块的时候指定所有的依赖dependencies,并且还要当做形参传到factory中,对于依赖的模块提前执行
define("module",["dep1","dep2"],functian(d1,d2){return someExportedValue;
});
require(["module","../file.js"],function(module,file){});
- 优点:
- 适合在浏览器环境中异步加载模块
- 可以并行加载多个模块
- 缺点:
- 提高了开发成本,代码的阅读和书写比较困难,模块定义方式的语义不畅
- 不符合通用的模块化思维方式,是一种妥协的实现
- 实现:
- RequireJS
- curl
CMD
Commons Module Definition规范和AMD很相似,尽保持简单,并与CommonsJS和NodeJS的Modules规范保持了很大的兼容性
define(function(require,exports,module){var $=require("jquery");var Spinning = require("./spinning");exports.doSomething = ...;module.exports=...;
});
- 优点:
- 依赖就近,延迟执行
- 可以很容易在NodeJS中运行缺点
- 依赖SPM打包,模块的加载逻辑偏重
- 实现
- Sea.js
- coolie
ES6模块
EcmaScript 6标准增加了JavaScript语言层面的模块体系定义。ES 6模块的设计思想, 是尽量静态化, 使编译时就能确定模块的依赖关系, 以及输入和输出的变量。Commons JS和AMD模块,都只能在运行时确定这些东西
import "jquery"
export function doStuff(){}
module "localModule"{}
- 优点:
- 容易进行静态分析
- 面向未来的Ecma Script标准
- 缺点:
- 原生浏览器端还没有实现该标准
- 全新的命令,新版的Node JS才支持
- 实现: Babel
大家期望的模块
系统可以兼容多种模块风格, 尽量可以利用已有的代码, 不仅仅只是JavaScript模块化, 还有CSS、图片、字体等资源也需要模块化。
7.3、安装Webpack
WebPack是一款模块加载器兼打包工具, 它能把各种资源, 如JS、JSX、ES 6、SASS、LESS、图片等都作为模块来处理和使用
安装:
npm install webpack -g
npm install webpack-cli -g
测试安装是否成功: npm list --depth=0 -g
配置: 创建 webpack.config.js
配置文件
-
entry:入口文件, 指定Web Pack用哪个文件作为项目的入口
-
output:输出, 指定WebPack把处理完成的文件放置到指定路径
-
module:模块, 用于处理各种类型的文件
-
plugins:插件, 如:热更新、代码重用等
-
resolve:设置路径指向
-
watch:监听, 用于设置文件改动后直接打包
module.exports = {entry:"",output:{path:"",filename:""},module:{loaders:[{test:/\.js$/,;\loade:""}]},plugins:{},resolve:{},watch:true }
直接运行
webpack
命令打包
7.4使用webpack
-
创建项目
-
创建一个名为modules的目录,用于放置JS模块等资源文件
-
在modules下创建模块文件,如hello.js,用于编写JS模块相关代码
//暴露一个方法:sayHi exports.sayHi = function(){document.write("<div>Hello Webpack</div>"); }
-
在modules下创建一个名为main.js的入口文件,用于打包时设置entry属性
//require 导入一个模块,就可以调用这个模块中的方法了 var hello = require("./hello"); hello.sayHi();
-
在项目目录下创建webpack.config.js配置文件,使用webpack命令打包
module.exports = {entry: './modules/main.js',mode: 'development',output: {filename: "./js/bundle.js"} };
-
在项目目录下创建HTML页面,如index.html,导入webpack打包后的JS文件
<!doctype html> <html lang="en"><head><meta charset="UTF-8"><title>Java学不会</title></head><body><script src="dist/js/bundle.js"></script></body> </html>
-
在IDEA控制台中直接执行webpack;如果失败的话,就使用管理员权限运行即可
-
运行HTML看效果
# 参数--watch 用于监听变化 webpack --watch
8、vue-router路由
8.1、说明
学习的时候,尽量的打开官方的文档
Vue Router是Vue.js官方的路由管理器。它和Vue.js的核心深度集成, 让构建单页面应用变得易如反掌。包含的功能有:
- 嵌套的路由/视图表
- 模块化的、基于组件的路由配置
- 路由参数、查询、通配符
- 基于Vue js过渡系统的视图过渡效果
- 细粒度的导航控制
- 带有自动激活的CSS class的链接
- HTML5 历史模式或hash模式, 在IE 9中自动降级
- 自定义的滚动行为
8.2、安装
基于第一个vue-cli
进行测试学习; 先查看node modules中是否存在vue-router
vue-router是一个插件包, 所以我们还是需要用npm/cnpm来进行安装的。打开命令行工具,进入你的项目目录,输入下面命令
cnpm install vue-router@3.1.3 --save-dev
如果在一个模块化工程中使用它,必须要通过Vue.use()明确地安装路由功能:
import Vue from 'vue'
import VueRouter from 'vue-router'
//显示声明使用VueRouter
Vue.use(VueRouter);
8.2、测试
-
先删除没有用的东西
-
components
目录下存放我们自己编写的组件 -
定义一个
Content.vue
的组件<template><div><h1>内容页</h1></div> </template><script>export default {name:"Content"} </script>
-
Main.vue
组件<template><div><h1>首页</h1></div> </template><script>export default {name:"Main"} </script>
-
安装路由,在src目录下,新建一个文件夹:
router
,专门存放路由,配置路由index.js,如下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:[{//路由路径path:'/content',//路由名称name:'content',//跳转到组件component:Content},{//路由路径path:'/main',//路由名称name:'main',//跳转到组件component:Main}]});
-
在
main.js
中配置路由import Vue from 'vue' import App from './App' import router from './router' //自动扫描index文件(路由配置)Vue.config.productionTip = falsenew Vue({el: '#app',//配置路由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>
9、实战快速上手
我们采用实战教学模式并结合ElementUI组件库,将所需知识点应用到实际中,以最快速度带领大家掌握Vue的使用;
9.1、创建工程
注意:命令行都要使用管理员模式运行
-
创建一个名为hello-vue的工程
vue init webpack hello-vue
-
安装依赖, 我们需要安装vue-router、element-ui、sass-loader和node-sass四个插件
进入工程目录 cd hello-vue 安装vue-routern cnpm install vue-router@3.1.3 --save-dev 安装element-ui npm i element-ui -S 安装依赖 npm install 安装SASS加载器 cnpm install sass-loader node-sass --save-dev 启功测试 npm run dev
-
Npm命令解释:
npm install moduleName
:安装模块到项目目录下npm install -g moduleName
:-g的意思是将模块安装到全局,具体安装到磁盘哪个位置要看npm config prefix的位置npm install -save moduleName
:–save的意思是将模块安装到项目目录下, 并在package文件的dependencies节点写入依赖,-S为该命令的缩写npm install -save-dev moduleName
:–save-dev的意思是将模块安装到项目目录下,并在package文件的devDependencies节点写入依赖,-D为该命令的缩写
9.2、创建登录页面
把没有用的初始化东西删掉!在源码目录中创建如下结构:
- assets:用于存放资源文件
- components:用于存放Vue功能组件
- views:用于存放Vue视图组件
- router:用于存放vue-router配置
创建首页视图,在views目录下创建一个名为Main.vue的视图组件:
<template><h1>首页</h1>
</template><script>
export default {name: "Main"
}
</script><style scoped></style>
创建登录页视图在views目录下创建名为Login.vue的视图组件,其中el-*的元素为ElementUI组件
<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-dialog title="温馨提示" :visible.sync="dialogVisiable" 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:"密码不可为空",tigger:"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 lang="scss" scoped>.login-box{border:1px solid #DCDFE6;width: 350px;margin:180px auto;padding: 35px 35px 15px 35px;border-radius: 5px;-webkit-border-radius: 5px;-moz-border-radius: 5px;box-shadow: 0 0 25px #909399;}.login-title{text-align:center;margin: 0 auto 40px auto;color: #303133;}
</style>
创建路由,在router目录下创建一个名为index.js
的vue-router路由配置文件
//导入vue
import Vue from 'vue';
import VueRouter from 'vue-router';
//导入组件
import Main from "../views/Main";
import Login from "../views/Login";
//使用
Vue.use(VueRouter);
//导出
export default new VueRouter({routes: [{//登录页path: '/main',component: Main},//首页{path: '/login',component: Login},]})
APP.vue
<template><div id="app"><router-view></router-view></div>
</template><script>export default {name: 'App'
}
</script>
main.js
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
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'Vue.use(router)
Vue.use(ElementUI)/* eslint-disable no-new */
new Vue({el: '#app',router,render:h=>h(App)
})
测试:在浏览器打开 http://localhost:8080/#/login
如果出现错误: 可能是因为sass-loader的版本过高导致的编译错误,当前最高版本是8.0.2,需要退回到7.3.1 ;
去package.json文件里面的 "sass-loader"的版本更换成7.3.1,然后重新cnpm install就可以了;
9.3、路由嵌套
嵌套路由又称子路由,在实际应用中,通常由多层嵌套的组件组合而成
-
创建用户信息组件,在 views/user 目录下创建一个名为 Profile.vue 的视图组件;
<template><h1>个人信息</h1> </template> <script>export default {name: "UserProfile"} </script> <style scoped> </style>
-
在用户列表组件在 views/user 目录下创建一个名为 List.vue 的视图组件
<template><h1>用户列表</h1> </template> <script>export default {name: "UserList"} </script> <style scoped> </style>
-
修改首页视图,我们修改 Main.vue 视图组件,此处使用了 ElementUI 布局容器组件,代码如下
<template><div><el-container><el-aside width="200px"><el-menu :default-openeds="['1']"><el-submenu index="1"><template slot="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-group></el-submenu><el-submenu index="2"><template slot="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: #006bfc;color: #333;line-height: 60px; } .el-aside {color: #5dc7d9; } </style>
-
配置嵌套路由修改 router 目录下的 index.js 路由配置文件,使用children放入main中写入子模块,代码如下
<template><div><el-container><el-aside width="200px"><el-menu :default-openeds="['1']"><el-submenu index="1"><template slot="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-group></el-submenu><el-submenu index="2"><template slot="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: #006bfc;color: #000000;line-height: 60px; } .el-aside {color: #5dc7d9; } </style>
-
路由嵌套实战效果图
9.4、参数传递
这里演示如果请求带有参数该怎么传递
用的还是上述例子的代码
修改一些代码 这里不放重复的代码了
第一种取值方式
-
第一种方式:
-
修改路由配置, 主要是router下的index.js中的 path 属性中增加了 :id 这样的占位符
{path: '/user/profile/:id',name: 'UserProfile',component: UserProfile },
-
传递参数:此时我们在Main.vue中的route-link位置处 to 改为了 :to,是为了将这一属性当成对象使用,注意 router-link 中的 name 属性名称 一定要和 路由中的 name 属性名称 匹配,因为这样 Vue 才能找到对应的路由路径;
<!--name是组件的名字 params是传的参数 如果要传参数的话就需要用v:bind:来绑定--> <router-link :to="{name:'UserProfile',params:{id:1}}">个人信息</router-link>
-
在要展示的组件Profile.vue中接收参数 使用 {{$route.params.id}}来接收
<template><!-- 所有的元素必须在根节点下--><div><h1>个人信息</h1>{{$route.params.id}}</div> </template>
-
-
第二种取值方式 使用props 减少耦合
- 修改路由配置 , 主要在router下的index.js中的路由属性中增加了 props: true 属性
{path: '/user/profile/:id', name:'UserProfile', component: UserProfile, props: true }
- 传递参数和之前一样 在Main.vue中修改route-link地址
<!--name是组件的名字 params是传的参数 如果要传参数的话就需要用v:bind:来绑定--> <router-link :to="{name:'UserProfile',params:{id:1}}">个人信息</router-link>
- 在Profile.vue接收参数为目标组件增加 props 属性
<template><div>个人信息{{ id }}</div> </template> <script>export default {props: ['id'],name: "UserProfile"} </script> <style scoped> </style>
- 修改路由配置 , 主要在router下的index.js中的路由属性中增加了 props: true 属性
-
传参效果图
9.5、组件重定向
重定向的意思大家都明白,但 Vue 中的重定向是作用在路径不同但组件相同的情况下,比如:
在router下面index.js的配置
{path: '/main',name: 'Main',component: Main
},
{path: '/goHome',redirect: '/main'
}
说明: 这里定义了两个路径,一个是 /main ,一个是 /goHome,其中 /goHome 重定向到了 /main 路径,由此可以看出重定向不需要定义组件;
使用的话,只需要在Main.vue设置对应路径即可;
<el-menu-item index="1-3"><router-link to="/goHome">回到首页</router-link>
</el-menu-item>
9.6、路由模式与 404
-
路由模式有两种:
- hash:路径带 # 符号,如 http://localhost/#/login
- history:路径不带 # 符号,如 http://localhost/login
-
修改路由配置,代码如下:
export default new Router({mode: 'history',routes: [] });
-
404 demo
-
创建一个NotFound.vue视图组件
<template><div><h1>404,你的页面走丢了</h1></div> </template> <script>export default {name: "NotFound"} </script> <style scoped> </style>
-
修改路由配置index.js
import NotFound from '../views/NotFound' {path: '*',component: NotFound }
-
效果图
-
9.7、路由钩子与异步请求
beforeRouteEnter
:在进入路由前执行
beforeRouteLeave
:在离开路由前执行
在Profile.vue中写
export default {name: "UserProfile",beforeRouteEnter: (to, from, next) => {console.log("准备进入个人信息页");next();},beforeRouteLeave: (to, from, next) => {console.log("准备离开个人信息页");next();}
}
参数说明:
- to:路由将要跳转的路径信息
- from:路径跳转前的路径信息
- next:路由的控制参数
- next() 跳入下一个页面
- next(’/path’) 改变路由的跳转方向,使其跳到另一个路由
- next(false) 返回原来的页面
- next((vm)=>{}) 仅在 beforeRouteEnter 中可用,vm 是组件实例
在钩子函数中使用异步请求
-
安装 Axios
cnpm install --save vue-axios
-
main.js引用 Axios
import axios from 'axios' import VueAxios from 'vue-axios' Vue.use(VueAxios, axios)
-
准备数据 : 只有我们的 static 目录下的文件是可以被访问到的,所以我们就把静态文件放入该目录下。
数据和之前用的json数据一样 需要的去上述axios例子里// 静态数据存放的位置 static/mock/data.json
-
在 beforeRouteEnter 中进行异步请求
export default {//第二种取值方式// props:['id'],name: "UserProfile",//钩子函数 过滤器beforeRouteEnter: (to, from, next) => {//加载数据console.log("进入路由之前")next(vm => {//进入路由之前执行getData方法vm.getData()});},beforeRouteLeave: (to, from, next) => {console.log("离开路由之前")next();},//axiosmethods: {getData: function () {this.axios({method: 'get',url: 'http://localhost:8080/static/mock/data.json'}).then(function (response) {console.log(response)})}} }
-
运行效果:
相关文章:
vue框架快速入门
vue 1、第一个Vue程序1.1、什么是Vue程序1.2、为什么要使用MVVM1.3、Vue1.4、第一个vue程序 2、基础语法2.1、v-bind2.2、v-if, v-else2.3、v-for2.4、v-on 3、Vue表单双绑、组件3.1、什么是双向数据绑定3.2、在表单中使用双向数据绑定3.3、什么是组件 4、Axios异步…...
Java连接顺丰开放平台
今天使用Java去访问顺丰的开放平台时,JSON转换一直不成功,最终发现是 可以看到这里是 "apiResultData": "{\"success\": .........它是以 " 开头的!!!如果是对象的话,那么…...
前端三剑客 - HTML
前言 前面都是一些基础的铺垫,现在就正式进入到web开发环节了。 我们的目标就是通过学习 JavaEE初阶,搭建出一个网站出来。 一个网站分成两个部分: 前端(客户端) 后端(服务器) 通常这里的客户端…...
【计算机视觉 | 自然语言处理】BLIP:统一视觉—语言理解和生成任务(论文讲解)
文章目录 一、前言二、试玩效果三、研究背景四、模型结构五、Pre-training objectives六、CapFilt架构七、Experiment八、结论 一、前言 今天我们要介绍的论文是 BLIP,论文全名为 Bootstrapping Language-Image Pre-training for Unified Vision-Language Understa…...
c++基础-运算符
目录 1关系运算符 2运算符优先级 3关系表达式的书写 代码实例: 下面是面试中可能遇到的问题: 1关系运算符 C中有6个关系运算符,用于比较两个值的大小关系,它们分别是: 运算符描述等于!不等于<小于>大于<…...
美术馆c++
题目: 杜老师非常喜欢玩一种叫做“美术馆”的数字游戏,蜗蜗看了之后决定也来试一试,他改编了这个游戏,规则如下: 有一个 n� 行 m� 列的方格,每一个格子中有一个数,数字…...
浅谈MySQL索引以及执行计划
MySQL索引及执行计划 🐪索引的作用🐫索引的分类(算法)🦙BTREE索引算法演变🦒Btree索引功能上的分类4.1 辅助索引4.2 聚集索引4.3 辅助索引和聚集索引的区别 🐘辅助索引分类🦏索引树高…...
在c++项目中使用rapidjson(有具体的步骤,十分详细) windows10系统
具体的步骤: 先下载rapidjson的依赖包 方式1:直接使用git去下载 地址:git clone https://github.com/miloyip/rapidjson.git 方式2:下载我上传的依赖包 将依赖包引入到项目中 1 将解压后的文件放在你c项目中 2 将rapidjson文…...
编译方式汇总:Makefile\configure\autogen.sh\configure.ac、Makefile.am文件
一、前言 文章目的:针对各种开源项目,由于部分项目文档写的不够详细,(或者是我太菜了),没有进行详细的介绍怎么编译该项目,导致花费过多时间在查找如何编译该项目上。因此该篇文章针对目前遇到的…...
explicit关键字
explicit关键字只能用来修饰构造函数。使用explicit可以禁止编译器自动调用拷贝初始化,还可以禁止编译器对拷贝函数的参数进行隐式转换。 那么什么是隐式转换呢? 类 命名 参数; //有参构造类 命名 命名对象; //拷贝构造&#x…...
[优雅的面试] 你了解python的对象吗
前情提要:小编面试,结果面试官着急去吃饭~又约了这次来面,不晓得又会问什么问题呢? 面试官大佬:小伙子来的挺准时的(赞赏的表情~),今天咱们接着聊哈,小伙子,你有对象了没?…...
【hello Linux】线程概念
目录 1. 线程概念的铺设 2. Linux线程概念 2.1 什么是线程 2.2 线程的优点 2.3 线程的缺点 2.4 线程异常 2.5 线程用途 3. Linux进程VS线程 4. Linux线程控制 4.1 POSIX线程库 4.2 创建线程 4.3 进程ID和线程ID 4.4 线程终止 4.5 线程等待 4.6 分离线程 Linux🌷 1…...
JavaWeb07(MVC应用01[家居商城]连接数据库)
目录 一.什么是MVC设计模式? 1.2 MVC设计模式有什么优点? 二.MVC运用(家居商城) 2.1 实现登录 2.2 绑定轮播【随机三个商品】 2.2.1 效果预览 index.jsp 2.3 绑定最新上架&热门家居 2.3.1 效果预览 2.3.2 代码实现 数据…...
如何使用电商API接口API接口如何应用
使用API接口 API(应用程序接口)是现代软件开发中必不可少的一部分,它通常允许软件与其他软件或服务进行交互。使用API可以大大提高软件的灵活性和可扩展性,并允许您轻松添加新的功能和服务,因此,API接口的…...
【移动端网页布局】流式布局案例 ⑥ ( 多排按钮导航栏 | 设置浮动及宽度 | 设置图片样式 | 设置文本 )
文章目录 一、多排按钮导航栏样式及核心要点1、实现效果2、总体布局设计3、设置浮动及宽度4、设置图片样式5、设置文本 二、完整代码实例1、HTML 标签结构2、CSS 样式3、展示效果 一、多排按钮导航栏样式及核心要点 1、实现效果 要实现下面的导航栏效果 ; 2、总体布局设计 该导…...
1. 先从云计算讲起
本章讲解知识点 什么是云计算? 为什么要用云计算? 物理服务器与云服务器对比 云计算服务类型 云计算部署类型 1. 什么是云计算? 云计算是一种通过计算机网络以服务的方式提供动态可伸缩的虚拟化资源的计算模式。按照服务层次分为IaaS、…...
ZooKeeper安装与配置集群
简介: ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,它提供了一个分布式环境中的高可用性、高性能、有序访问的数据存储,可以让分布式应用程…...
浅谈Mysql的RR和RC隔离级别的主要区别
MySQL默认为RR级别 首先默认RR是因为mysql为了保证在主从同步过程中数据的安全的问题(涉及到binlog三种格式)。 就是说两个并发事务数AB,A先开启事物最后提交也是最后,事务B开启和提交都在A内部,由于隔离级别不同&…...
Build生成器模式
设计模式简述 设计模式的核心在于提供了相关问题的解决方案,使得人们可以更加简单方便地复用成功的设计和体系结构。 生成器模式(创建型设计模式) 意图:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以…...
C++程序设计——常见C++11新特性
一、列表初始化 1.C98中{}的初始化问题 在C98中,允许使用花括号{}对数组元素进行统一的列表初始化值设定,比如: 但是对于一些自定义类型,就无法使用这样的方式进行初始化了,比如: 就无法通过编译ÿ…...
Rust main 函数返回值类型不能是 String
是的,Rust 的 main 函数返回值类型不能是 String。 Rust 的 main 函数只能返回以下几种类型之一: ():表示空类型,不返回任何值。i32:表示程序的退出码,通常非零值表示执行失败,0 表示执行成功…...
视频里的音乐怎么转换成mp3格式?
视频里的音乐怎么转换成mp3格式?视频里的音乐转换为mp3的原因有很多,主要是因为mp3格式是一种音频格式,文件大小较小,更易于存储和传输。相比之下,视频格式则是一种视频文件格式,虽然包含音频,但…...
CSS3 grid网格布局
文章目录 CSS3 grid网格布局概述grid属性说明使用grid-template-rows & grid-template-columns 定义行高和列宽grid-auto-flow 定义项目的排列顺序grid-auto-rows & grid-auto-columns 定义多余网格的行高和列宽row-gap & column-gap 设置行间距和列间距gap 简写形…...
SPSS如何进行均值比较和T检验之案例实训?
文章目录 0.引言1.均值过程2.单样本T检验3.独立样本T检验4.成对样本T检验 0.引言 因科研等多场景需要进行数据统计分析,笔者对SPSS进行了学习,本文通过《SPSS统计分析从入门到精通》及其配套素材结合网上相关资料进行学习笔记总结,本文对均值…...
Packet Tracer - 配置交换机端口安全
Packet Tracer - 配置交换机端口安全 地址分配表 设备 接口 IP 地址 子网掩码 S1 VLAN 1 10.10.10.2 255.255.255.0 PC1 NIC 10.10.10.10 255.255.255.0 PC2 NIC 10.10.10.11 255.255.255.0 非法笔记本电脑 NIC 10.10.10.12 255.255.255.0 目标 第 1 部…...
一图看懂 aiohttp 模块:基于 asyncio 的异步HTTP网络库, 资料整理+笔记(大全)
本文由 大侠(AhcaoZhu)原创,转载请声明。 链接: https://blog.csdn.net/Ahcao2008 一图看懂 aiohttp 模块:基于 asyncio 的异步HTTP网络库, 资料整理笔记(大全) 摘要模块图类关系图模块全展开【aiohttp】统计常量模块1 aiohttp.hd…...
Linux + 香橙派 + V4L2 + http 实现远程监控摄像头在网页端显示
项目场景: 项目需求,需要做一个基于边缘端的人脸识别远程监控摄像头并在网页前端展示 ,这里采用国产香橙派作为边缘计算终端,安装ubuntu系统,系统中采用v4l2接口对摄像头进行获取,当客户端通过网页进行请求…...
《编码——隐匿在计算机软硬件背后的语言》精炼——第15-16章(十六进制,RAM)
“学习如春起之苗,不见其增,日有所长。” —— 宋代朱熹 文章目录 十六进制十六进制概述十六进制表字节到十六进制 存储器特定的读功能特定的写功能RAM大型RAM阵列 十六进制 十六进制概述 十六进制是一种适用于计算机的进制法。在十进制中,…...
leetcode.1376 通知所有员工所需的时间 - bfs/dfs + 树
1376. 通知所有员工所需的时间 目录 一、bfs 二、dfs 题目: 公司里有 n 名员工,每个员工的 ID 都是独一无二的,编号从 0 到 n - 1。公司的总负责人通过 headID 进行标识。在 manager 数组中,每个员工都有一个直属负责人&#x…...
AtCoder Beginner Contest 300——A-G题讲解
蒟蒻来讲题,还望大家喜。若哪有问题,大家尽可提! Hello, 大家好哇!本初中生蒟蒻讲解一下AtCoder Beginner Contest 300这场比赛的A-G题! A - N-choice question 原题 Problem Statement Given integers A A A and…...
做外国订单有什么网站/百度识图网页版在线
集线器-------集线器也叫Hub,工作在物理层(最底层),没有相匹配的软件系统,是纯硬件设备。集线器主要用来连接计算机等网络终端。集线器为共享式带宽,连接在集线器上的任何一个设备发送数据时,其…...
商业网站服务/搜狗seo排名软件
/* 在BC31下编译 */ /* compile under Borland C 3.1 *//* 对四则混合运算所提取的形式化表达式(生成式) <exp> -> <term> { <addop> <term> } <addop> -> | - <term> -> <factor> { <mulop> <factor> } <…...
三亚做网站服务/seo搜索引擎优化怎么优化
http://www.cocoachina.com/industry/20131106/7304.html 转载于:https://www.cnblogs.com/sgdkg/p/4365491.html...
水泵行业网站怎么做/宁波网络推广方法
Long.parseLong(String)方法,将 string 参数解析为有符号十进制 ,返回一个long的result基本类型值 Long.ValueOf(String) ,方法得到的值非常相似。只是最后被转换为一个Long的包装类。...
海南手机网站建设/天津seo渠道代理
本博文使用的数据库是MySQL和MongoDB数据库。安装MySQL可以参照我的这篇博文:https://www.cnblogs.com/tszr/p/12112777.html其中操作Mysql使用到的python模块是pymysql,下面是有关这个模块的使用说明:创建一个数据库testcreate DATABASE taobao;Navicat…...
建一个网站需要哪些费用/软文发布平台与板块
文/小伊评科技还是那个结论,我不认为现阶段的鸿蒙OS能够在手机这种载体上真正的挑战Android以及IOS,但是未来就不一定了。作为例子,早些年微软凭借WindowPhone以及对于诺基亚的扶持都没能从IOS和安卓手上抢下市场,反而最后落得一个…...