Vue
1、概述
- 一套用于构建用户界面的渐进式JavaScript框架
- 自底向上逐层应用
- Vue 的核心库只关注视图层
- 核心就是实现了DOM监听与数据绑定
- 官网:https://cn.vuejs.org/v2/guide/
2、MVVM
- MVVM(Model-View-ViewModel)是一种软件设计模式
- 是一种简化用户界面的事件驱动编程方式
- 源于MVC,核心是ViewModel层,负责转换Model中的数据对象来让数据变得更容易管理和使用
- Model:模型层, 在这里表示JavaScript对象
- View:视图层, 在这里表示DOM(HTML操作的元素)
- ViewModel:连接视图和数据的中间件, Vue.js就是MVVM中的View Model层的实现者
- ViewModel 层作用:
- 向上与视图层进行双向数据绑定
- 向下与Model层通过接口请求进行数据交互
- 优点:
- 低耦合:视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
- 可复用:你可以把一些视图逻辑放在一个ViewModel里面,让很多View重用这段视图逻辑。
- 独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewMode),设计人员可以专注于页面设计。
- 可测试:界面素来是比较难以测试的,而现在测试可以针对ViewModel来写。
在MVVM架构中, 是不允许数据和视图直接通信的, 只能通过ViewModel来通信, 而View Model就是定义了一个Observer观察者
3、HelloVue
3.1、CDN
<script src=“https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js”></script>`
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
3.2、HelloVue.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello,vue!</title>
</head>
<body>
<!--view 层-->
<!--将数据绑定到页面元素-->
<div id="app">
{{message}}
</div>
</body>
<!--引入js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
//Vue实例
var vm = new Vue({
el:"#app",//绑定元素id
//model 层
data:{
message:"hello,vue!"//数据对象中有一个名为message的属性,并设置了初值
}
});
</script>
</html>
3.3、测试
可以在控制台直接输入vm.message来修改值, 中间是可以省略data的, 在这个操作中, 并未主动操作DOM, 就让页面的内容发生了变化, 这就是借助了Vue的数据绑定功能实现的; MV VM模式中要求View Model层就是使用观察者模式来实现数据的监听与绑定, 以做到数据与视图的快速响应。
4、基础语法指令
**注意:*使用 v- 属性绑定数据是不需要 双花括号 包裹的
4.1、v-bind
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>v-bind</title>
</head>
<body>
<div id="app">
<span v-bind:title="message">鼠标悬停查看绑定的提示信息</span>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data:{
message: '页面加载于' + new Date().toLocaleString()
}
})
</script>
</html>
将这个元素节点的title特性和Vue实例的message属性保持一致
4.2、v-if,v-else
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>v-if,else</title>
</head>
<body>
<div id="app">
<h1 v-if="ok">Yes</h1>
<h1 v-else>No</h1>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data:{
ok: true
}
})
</script>
</html>
控制台可以输入 vm.data.ok/vm.ok 进行改变
4.3、v-else-if
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>v-else-if</title>
</head>
<body>
<div id="app">
<h1 v-if="type === 'A'">A</h1>
<h1 v-else-if="type === 'B'">B</h1>
<h1 v-else>C</h1>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data:{
type: ""
}
})
</script>
</html>
4.4、v-for
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<li v-for="(item,index) in items">
{{item.message}}--{{index}}
</li>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
items:[
{message:"Java"},
{message:"Spring"},
{message:"Vue"}
]
}
})
</script>
</html>
- items 是数组,item 是数组元素迭代的别名
- 控制台输入 vm.items.push({message:‘study’}) 可以追加数据,增加输出
4.5、v-on
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>v-on</title>
</head>
<body>
<div id="app">
<button v-on:click="sayHi">点我</button>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
message: "hello!"
},
methods: {
sayHi:function (event) {
//this 指向当前 vue 实例
alert(this.message);
}
}
})
</script>
</html>
- v-on监听事件,事件有Vue的事件、和前端页面本身的一些事件
- 事件绑定到实例的 methods
5、双向绑定
可以用 v-model 指令在表单、及元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇, 但 v-model 本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
**注意:**v-model 会忽略所有表单元素的 value、checked、selected 特性的初始值而总是将 Vue实例的数据作为数据来源。应该通过 JavaScript 在组件的 data 选项中声明初始值!
5.1、单行文本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>单行文本</title>
</head>
<body>
<div id="app">
输入的文本为:<input type="text" v-model="message">{{message}}
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var cm = new Vue({
el: "#app",
data: {
message: ""
}
})
</script>
</html>
5.2、多行文本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>多行文本</title>
</head>
<body>
<div id="app">
多行文本:<textarea type="text" v-model="message"></textarea>
多行文本是:{{message}}
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var cm = new Vue({
el: "#app",
data: {
message: "hello"
}
})
</script>
</html>
5.3、单复选框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>单复选框</title>
</head>
<body>
<div id="app">
单复选框:<input type="checkbox" v-model="checked">{{checked}}
<label>{{checked}}</label>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var cm = new Vue({
el: "#app",
data: {
checked: true
}
})
</script>
</html>
5.4、多复选框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>多复选框</title>
</head>
<body>
<div id="app">
多复选框:
<input type="checkbox" value="Jack" v-model="checkedNames">
<label>Jack</label>
<input type="checkbox" value="Join" v-model="checkedNames">
<label>join</label>
<input type="checkbox" value="Mike" v-model="checkedNames">
<label>Mike</label>
<span>选中的值:{{checkedNames}}</span>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var cm = new Vue({
el: "#app",
data: {
checkedNames: []
}
})
</script>
</html>
5.5、单选按钮
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>单选按钮</title>
</head>
<body>
<div id="app">
单选框按钮
<input type="radio" value="One" v-model="picked">
<label>One</label>
<input type="radio" value="Two" v-model="picked">
<label>Two</label>
<span>选中的值:{{picked}}</span>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var cm = new Vue({
el: "#app",
data: {
picked:''
}
})
</script>
</html>
5.6、下拉框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>下拉框</title>
</head>
<body>
<div id="app">
下拉框:
<select v-model="pan">
<option value="" disabled>---请选择---</option>
<option>A</option>
<option>B</option>
<option>C</option>
<option>D</option>
</select>
<span>value:{{pan}}</span>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var cm = new Vue({
el: "#app",
data: {
pan:""
}
})
</script>
</html>
v-model 表达式的初始值未能匹配任何选项,元系将被渲染为“未选中”状态。 在iOS中, 这会使用户无法选择第一个选项,因为这样的情况下,iOS不会触发change事件。因此,添加像上面这样提供一个值为空的禁用选项。
6、component
6.1、第一个 component
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>component</title>
</head>
<body>
<div id="app">
<yuan></yuan>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
//注册组件
Vue.component("yuan",{
template: '<li>Hello</li>'
})
//实例化vue
var vm = new Vue({
el: "#app"
})
</script>
</html>
- Vue.component() :注册组件
- yuan :自定义组件名称
- template :组件模板
6.2、props 传参
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>props</title>
</head>
<body>
<div id="app">
<yuan v-for="item in items" v-bind:list="item"></yuan>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
//注册组件
Vue.component("yuan",{
props: ['list'],
template: '<li>{{list}}</li>'
})
//实例化vue
var vm = new Vue({
el: "#app",
data: {
items: ["Java","Spring","Vue"]
}
})
</script>
</html>
注意:默认规则下props属性里的值不能为大写;
- **v-for=“item in items”:**遍历 Vue 实例中定义的名为 items 的数组,并创建同等数量的组件
- **v-bind:list=“item”:**将遍历 item 项绑定到组件中 props 定义名为 list 属性上;= 号左边的 list 为props定义的属性名,右边的为 item in items 中遍历的 item 项的值
7、Axios
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Axios</title>
<style>
/*v-cloak解决闪烁问题*/
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<div>地名:{{info.name}}</div>
<div>地址:{{info.address.country}}--{{info.address.city}}--{{info.address.street}}</div>
<div>链接:<a v-bind:href="info.url">{{info.url}}</a> </div>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
var vm = new Vue({
el:"#app",
data:{},
data(){
return{
info: {
name: null,
address: {
country: null,
city: null,
street: null
},
url: null
}
}
},
//钩子函数
mounted(){
axios.get('../data.json').then(reponse=>(
this.info = reponse.data
))
}
})
</script>
</html>
- v-cloak 解决页面闪烁问题(不会出现{{message}}这样的信息)
- v-bind 将 a:href 的属性值与 Vue 实例中的数据进行绑定
8、生命周期
Vue实例有一个完整的生命周期,也就是从开始创建初始化数据、编译模板、挂载DOM、渲染一更新一渲染、卸载等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。
在Vue的整个生命周期中,它提供了一系列的事件,可以让我们在事件触发时注册JS方法,可以让我们用自己注册的JS方法控制整个大局,在这些事件响应方法中的this直接指向的是Vue的实例。
9、computed
计算属性的重点突出在属性两个字上(属性是名词),首先它是个属性其次这个属性有计算的能力(计算是动词),这里的计算就是个函数:简单点说,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性),可以想象为缓存
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>compute</title>
</head>
<body>
<div id="app">
<p>currentTime1:{{currentTime1()}}</p>
<p>currentTime2:{{currentTime2}}</p>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
message: "message"
},
methods:{
currentTime1:function () {
return Date.now();
}
},
computed:{
currentTime2:function () {
this.message;
return Date.now();
}
}
})
</script>
</html>
- methods :方法
- computed :属性,this.message是为了能够让currentTime2观察到数据变化而变化
- 如何在方法中的值发生了变化,则缓存就会刷新!可以在控制台使用 vm.message=”xxx", 改变下数据的值,再次测试观察效果
- 调用方法时,每次都需要讲行计算,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?此时就可以考虑将这个结果缓存起来,采用计算属性可以很方便的做到这点,计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销
10、slot
使用 slot 元素作为承载分发内容的出口,作者称其为插槽,可以应用在组合组件的场景中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Slot</title>
</head>
<body>
<div id="app">
<yuan>
<yuan-title slot="yuan-title" :title="study"></yuan-title>
<yuan-items slot="yuan-items" v-for="(item,index) in yuanItems" v-bind:item="item" v-bind:index="index"></yuan-items>
<!--简写-->
<yuan-items slot="yuan-items" v-for="(item,index) in yuanItems" :item="item" :index="index"></yuan-items>
</yuan>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
//插槽组件
Vue.component('yuan',{
template:'<div>\
<slot name="yuan-title"></slot>\
<ul>\
<slot name="yuan-items"></slot>\
</ul>\
</div>'
});
//标题组件
Vue.component('yuan-title',{
props: ['title'],
template: '<div>{{title}}</div>'
});
//内容组件
Vue.component('yuan-items',{
props: ['item','index'],
template:"<li>{{index+1}},{{item}}</li>"
});
//实例化Vue初始化数据
var vm = new Vue({
el: "#app",
data: {
study: 'goodstudy',
yuanItems:['Java','Spring','Vue']
}
})
</script>
</html>
11、emit
组件删除 Vue 实例数据,this.$emit(‘事件名’,参数)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>emit</title>
</head>
<body>
<div id="app">
<yuan>
<yuan-title slot="yuan-title" :title="study"></yuan-title>
<!--<yuan-items slot="yuan-items" v-for="(item,index) in yuanItems" v-bind:item="item" v-bind:index="index"></yuan-items>-->
<!--简写-->
<yuan-items slot="yuan-items"
v-for="(item,index) in yuanItems"
:item="item" :index="index" :key="index"
@remove="removeItem(index)"></yuan-items>
<!--@remove 绑定自定义事件 @ = v:on -->
</yuan>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
//插槽组件
Vue.component('yuan',{
template:'<div>\
<slot name="yuan-title"></slot>\
<ul>\
<slot name="yuan-items"></slot>\
</ul>\
</div>'
});
//标题组件
Vue.component('yuan-title',{
props: ['title'],
template: '<div>{{title}}</div>'
});
//内容组件
Vue.component('yuan-items',{
props: ['index','item'],
template:`<li>{{index}}——{{item}}<button @click="remove">删除</button></li>`,
methods: {
remove:function (index){
//调用自定义事件方法
//remove为自定义方法名
this.$emit('remove',index)
}
}
});
var vm = new Vue({
el: "#app",
data: {
study: 'goodstudy',
yuanItems:['Java','Spring','Vue']
},
methods: {
removeItem:function (index){
console.log("删除了" + this.yuanItems[index])
this.yuanItems.splice(index,1);
}
}
})
</script>
</html>
12、vue-cli
12.1、安装
-
安装 nodejs:http://nodejs.cn/download/
-
node-v , npm-v 测试
-
环境配置:
-
这里的环境配置主要配置的是npm安装的全局模块所在的路径,以及缓存cache的路径,之所以要配置,是因为以后在执行类似:npm install express [-g] (后面的可选参数-g,g代表global全局安装的意思)的安装语句时,会将安装的模块安装到【C:\Users\用户名\AppData\Roaming\npm】路径中,占C盘空间
-
在 D:\nodejs 下创建两个文件夹 【node_global】及【node_cache】
-
输入命令:
npm config set prefix "D:\nodejs\node_global" npm config set cache "D:\nodejs\node_cache"
-
配置环境变量:
- 新建系统变量:NODE_PATH:D:\nodejs\node_global\node_modules
- 将用户变量 Path 修改为 D:\nodejs\node_global
- 添加变量 Path :D:\nodejs\node_global
-
-
安装淘宝镜像加速器 Cnpm:npm install cnpm -g
-
安装 vue-cli:cnpm install vue-cli -g
-
vue-list 测试
12.2、使用
- 创建一个基于webpack模板的vue应用程序: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
13、webpack
WebPack是一款模块加载器兼打包工具, 它能把各种资源, 如JS、JSX、ES 6、SASS、LESS、图片等都作为模块来处理和使用。
13.1、安装
npm install webpack -g
npm install webpack-cli -g
13.2、使用
-
建一个项目
-
建一个 modules 包
-
hello.js
//暴露方法 exports.sayHi = function () { document.write("<h1>webpack</h1>") }
-
main.js
//require 导入一个模块,就可以调用该模块的方法 var hello = require("./hello"); hello.sayHi();
-
webpack.config.js
module.exports = { entry:'./modules/main.js', output:{ filename: "./js/bundle.js" } };
-
webpack打包
生成 dist/js/bundle.js 文件
-
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>webpack</title> </head> <body> <script src="dist/js/bundle.js"></script> </body> </html>
14、vue-router
路由管理器
14.1、安装
-
先查看 node modules 中是否存在 vue-router
-
在当前目录下进行安装该插件
npm install vue-router --save-dev
14.2、使用
- 新建 components 文件夹,创建组件
Main.vue
<template>
<h1>首页</h1>
</template>
<script>
export default {
name: "Main"
}
</script>
<style scoped>
</style>
Content.vue
<template>
<h1>内容页</h1>
</template>
<script>
export default {
name: "Content"
}
</script>
<style scoped>
</style>
- 新建 router 文件夹,编写 index.js
import Vue from 'vue'
import VueRouter from "vue-router";
import Content from "../components/Content";
import Main from "../components/Main";
//使用路由
Vue.use(VueRouter);
//配置到处路由
export default new VueRouter({
routes:[
{
//路由路径
path: '/content',
//名字
name: 'content',
//跳转组件
component:Content
},{
//路由路径
path: '/main',
//名字
name: 'main',
//跳转组件
component:Main
}
]
});
- main.js 使用路由
import Vue from 'vue'
import App from './App'
import VueRouter from "vue-router";
import router from './router'//自动扫描里面路由配置
Vue.config.productionTip = false
//使用路由
Vue.use(VueRouter)
new Vue({
el: '#app',
//配置路由
router,
components: { App },
template: '<App/>'
})
- App.vue 使用组件
<template>
<div id="app">
<h1>Vue</h1>
<router-link to="/main">首页</router-link>
<router-link to="/content">内容页</router-link>
<!--展示视图-->
<router-view></router-view>
</div>
</template>
<script>
import Content from "./components/Content";
import Main from "./components/Main";
export default {
name: 'App',
components:{
Content,
Main
}
}
</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>
15、elementUI
依赖
#进入工程目录
cd hello-vue
#安装vue-routern
npm install vue-router --save-dev
#安装element-ui
npm i element-ui -S
#安装依赖
npm install
# 安装SASS加载器
cnpm install sass-loader node-sass --save-dev
#启功测试
npm run dev
启动失败,可能是 sass-loader 版本过高,需要回退版本,修改 package.json 文件 “sass-loader”: “^7.3.1”,重新 install
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为该命令的缩写
15.1、Views
15.1.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-dialog
title="温馨提示"
:visible.sync="dialogVisible"
width="30%">
<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 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>
15.1.2、Main.vue
<template>
<h1>首页</h1>
</template>
<script>
export default {
name: "Main"
}
</script>
<style scoped>
</style>
15.2、router
index.js
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
}
]
}
15.3、App.vue
<template>
<div id="app">
<router-view></router-view>
</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>
15.4、main.js
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)
new Vue({
el: '#app',
router,
render:h=>h(App)//ElementUI
})
地址栏输入 login 进入
16、路由嵌套
routes:[
{
path: '/main',
component: Main,
//嵌套路由
children: [
{
path: '/user/profile',
name: 'UserProFile',
component:UserProFile,
},
{
path: '/user/List',
component: UserList}
]
},
{
path: '/login',
component: Login
},
//重定向
{
path: '/goHome',
redirect: '/main'
}
]
17、参数传递
17.1、第一种方式
Main.Vue
<el-menu-item index="1-1">
<!--name:组件名 params:传递参数-->
<router-link :to="{name:'UserProFile',params:{id:1}}">个人信息</router-link>
</el-menu-item>
index.js
path: '/main',
component: Main,
//嵌套路由
children: [
{
path: '/user/profile/:id',
name: 'UserProFile',
component:UserProFile,
},
{
path: '/user/List',
component: UserList}
]
ProFile.Vue
<template>
<div>
<h1>个人信息</h1>
{{$route.params.id}}
</div>
</template>
<script>
export default {
name: "UserProFile"
}
</script>
<style scoped>
</style>
17.2、第二种方式
Main.Vue
<el-menu-item index="1-1">
<!--name:组件名 params:传递参数-->
<router-link :to="{name:'UserProFile',params:{id:1}}">个人信息</router-link>
</el-menu-item>
index.js
path: '/main',
component: Main,
//嵌套路由
children: [
{
path: '/user/profile',
name: 'UserProFile',
component:UserProFile,
props: true
},
{
path: '/user/List',
component: UserList}
]
ProFile.Vue
<template>
<div>
<h1>个人信息</h1>
{{id}}
</div>
</template>
<script>
export default {
props: ['id'],
name: "UserProFile"
}
</script>
<style scoped>
</style>
18、路由模式
18.1、hash
- 默认方式,路径带 # 符号,如 http://localhost/#/login
18.2、history
- 路径不带 # 符号,如 http://localhost/login
export default new Router({
mode: 'history',
routes: []
})
19、404
创建 NotFound.vue 视图组件
<template>
<div>
<h1>404,你的页面走丢了</h1>
</div>
</template>
<script>
export default {
name: "NotFound"
}
</script>
<style scoped>
</style>
修改路由配置文件
import NotFound from "../views/NotFound";
//404
{
path: '*',
component: NotFound
}
20、路由钩子
20.1、参数方法
**beforeRouteEnter:**进入路由前执行
**beforeRouteLeave:**离开路由前执行
<script>
export default {
props: ['id'],
name: "UserProFile",
beforeRouteEnter:(to,from,next) => {
console.log('进入路由之前')
next()
},
beforeRouteLeave: (to,from,next) => {
console.log('进入路由之后')
next()
}
}
</script>
参数说明:
- to:路由将要跳转的路径信息
- from:路径跳转前的路径信息
- next:路由的控制参数
- next() 跳入下一个页面
- next(’/path’) 改变路由的跳转方向,使其跳到另一个路由
- next(false) 返回原来的页面
- next((vm)=>{}) 仅在 beforeRouteEnter 中可用,vm 是组件实例
20.2、异步请求
-
安装 Axios:cnpm install --save vue-axios
-
引用 Axios:
import axios from 'axios' import VueAxios from 'vue-axios' Vue.use(VueAxios, axios)
-
准备数据,放入 static/mock/data.json
{ "name": "Java", "url": "https://blog.kuangstudy.com", "page": 1, "isNonProfit": true, "address": { "street": "含光门", "city": "陕西西安", "country": "中国" }, "links": [ { "name": "bilibili", "url": "https://space.bilibili.com/95256449" }, { "name": "Java", "url": "https://blog.kuangstudy.com" }, { "name": "百度", "url": "https://www.baidu.com/" } ] }
-
beforeRouteEnter 中进行异步请求
<script> export default { props: ['id'], name: "UserProFile", beforeRouteEnter:(to,from,next) => { console.log('进入路由之前') //加载数据 next(vm => { //进路由前执行 getData() 方法 vm.getData(); }) }, beforeRouteLeave: (to,from,next) => { console.log('进入路由之后') next() }, methods: { getData() { this.axios({ method: 'get', url: 'http://localhost:8080/static/mock/data.json' }).then((response) => { console.log(response) }) } } } </script>
beforeRouteEnter 中可用,vm 是组件实例
20.2、异步请求
-
安装 Axios:cnpm install --save vue-axios
-
引用 Axios:
import axios from 'axios' import VueAxios from 'vue-axios' Vue.use(VueAxios, axios)
-
准备数据,放入 static/mock/data.json
{ "name": "Java", "url": "https://blog.kuangstudy.com", "page": 1, "isNonProfit": true, "address": { "street": "含光门", "city": "陕西西安", "country": "中国" }, "links": [ { "name": "bilibili", "url": "https://space.bilibili.com/95256449" }, { "name": "Java", "url": "https://blog.kuangstudy.com" }, { "name": "百度", "url": "https://www.baidu.com/" } ] }
-
beforeRouteEnter 中进行异步请求
<script> export default { props: ['id'], name: "UserProFile", beforeRouteEnter:(to,from,next) => { console.log('进入路由之前') //加载数据 next(vm => { //进路由前执行 getData() 方法 vm.getData(); }) }, beforeRouteLeave: (to,from,next) => { console.log('进入路由之后') next() }, methods: { getData() { this.axios({ method: 'get', url: 'http://localhost:8080/static/mock/data.json' }).then((response) => { console.log(response) }) } } } </script>