Vue
一、Vue核心
数据驱动,组件化
Soc(关注点分离原则)
HTML+CSS+JS -> 视图层:给用户看,刷新后台给的数据
网络通信:axios
页面跳转:vue-router
状态管理:vuex
Vue-UI:ICE
1.1、什么是MVVM
MVVM源自于经典的MVC(Model-View-Controller)模式。MVVM的核心是ViewModel层,负责转换Model中的数据对象来让数据变得更容易管理和使用。其作用如下:
- 该层向上与视图层进行双向数据绑定
- 向下与Model层通过接口请求进行数据交互
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
1)MVVM模式的实现者
-
Model:模型层, 在这里表示JavaScript对象
-
View:视图层, 在这里表示DOM(HTML操作的元素)
-
ViewModel:连接视图和数据的中间件, Vue.js就是MVVM中的View Model层的实现者
-
在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) 的长处, 并拥有自己独特的功能,如:计算属性
- 开源,社区活跃度高
二、Vue语法
<!-- 1.导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el:"#app", //通过element元素绑定id为app的模块
//Model:数据
data:{
message: ""
}
});
</script>
以v-开头,位于便签中
2.1、判断-循环
v-if
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--View层 模版Template-->
<div id="app">
<h1 v-if="ok">Yes</h1>
<h1 v-else>No</h1>
</div>
<!-- 导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el:"#app", //通过element元素绑定id为app的模块
//Model:数据
data:{
ok: true
}
});
</script>
</body>
</html>
测试
1.在浏览器上运行,打开控制台
2.在控制台输入vm.ok=false
然后回车,你会发现浏览器中显示的内容会直接变成NO
注:使用vm.
属性绑定数据是不需要双花括号
包裹的
for
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue数组练习</title>
</head>
<body>
<!--View层 模版Template-->
<div id="app">
<!-- 类似Foreach循环 -->
<li v-for="item in items">
{{item.message}}
</li>
</div>
<!-- 导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app", //通过element元素绑定id为app的模块
//Model:数据
data: {
//数组
items: [{
message: 'Darwin'
},
{
message: 'Zhong'
},
{
message: 'Clinkz'
},
]
}
});
</script>
</body>
</html>
2.2、事件
on
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--View层 模版Template-->
<div id="app">
<button v-on:click="sayHi">Click</button>
</div>
<!-- 导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app", //通过element元素绑定id为app的模块
//Model:数据
data: {
message: 'Darwin'
},
methods: { //方法必须定义在methods中
sayHi: function () {
alert(this.message);
}
}
});
</script>
</body>
</html>
双向绑定
v-model
数据双向绑定, 即当数据发生变化的时候, 视图也就发生变化, 当视图发生变化的时候,数据也会跟着同步变化。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue双向绑定</title>
</head>
<body>
<!--View层 模版Template-->
<div id="app">
下拉框:
<select v-model="message">
<option value="" disabled>请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
value:{{message}}
</div>
<!-- 1.导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app", //通过element元素绑定id为app的模块
//Model:数据
data: {
message: ""
}
});
</script>
</body>
</html>
2.3、网络通信
-
JQuery.ajax()
-
Axios
用在浏览器和Nodejs的异步通信框架,实现AJAX异步通信功能
- 从浏览器创建 XMLHttpRequest
- 从node.js创建http请求
- 支持Promise API [JS中链式编程]
- 拦截请求和响应
- 转换请求数据和响应数据
- 取消请求
- 自动转换JSON数据
- 客户端支持防御XSRF(跨站请求伪造)
伪数据:
{
"name": "darwin",
"url": "https://www.google.com",
"page": 1,
"isNonProfit": true,
"address": {
"street": "含光门",
"city": "陕西西安",
"country": "中国"
},
"links": [
{
"name": "bilibili",
"url": "https://bilibili.com"
},
{
"name": "darwin",
"url": "https://www.google.com"
},
{
"name": "百度",
"url": "https://www.baidu.com/"
}
]
}
测试代码:
<!DOCTYPE html>
<html lang="en" xmlns:v-binf="http://www.w3.org/1999/xhtml" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--v-cloak 解决闪烁问题-->
<style>
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div id="vue" 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>
<!--引入js文件-->
<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 type="text/javascript">
var vm = new Vue({
el:"#vue",
//data:属性:vm
data(){
return{
info:{
name:null,
address:{
country:null,
city:null,
street:null
},
url:null
}
}
},
mounted(){//钩子函数
axios
.get('../data.json')
.then(response=>(this.info=response.data));
}
});
</script>
</body>
</html>
说明:
- v-bind将a:href的属性值和vue中的实例数据绑定
- 使用axios框架的get方法请求ajax并自动将数据封装到vue实例对象
- data中的数据结构必须和ajax响应的数据格式匹配
2.4、计算属性
计算出来的结果保存在属性中,内存中运行:虚拟DOM
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--View层 模版Template-->
<div id="app">
<p>currentTime1:{{currentTime1()}}</p>
<p>currentTime2:{{currentTime2}}</p>
</div>
<!-- 导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app", //通过element元素绑定id为app的模块
data: {
message: "hello,Vue!"
},
methods: {
currentTime1: function () {
return Date.now(); //返回当前时间戳
}
},
computed: { //计算属性:methods和computed里的方法不能重名
//跑一次之后就缓存到内存中,如果改变其中数据则再次重新计算
currentTime2: function () {
this.message; //
return Date.now(); //返回当前时间戳
}
}
});
</script>
</body>
</html>
2.5、组件化
自定义组件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>定义一个Vue组件</title>
</head>
<body>
<!--View层 模版Template-->
<div id="app">
<darwin v-for="item in items" v-bind:bind="item"></darwin>
<li v-for="item in items">{{item}}</li>
</div>
<!-- 1.导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
//定义一个Vue组件
Vue.component("darwin", {
props: ['bind'], //props属性:接收参数
template: ' <li>{{bind}}</li>'
})
var vm = new Vue({
el: "#app", //通过element元素绑定id为app的模块
//Model:数据
data: {
message: "",
items: ["Java", "GoLang", "Python"]
}
});
</script>
</body>
</html>
动态可拔插:slot插槽
通过定义slot形成插槽,自定义组件插入插槽实现动态可拔插
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--View层 模版Template-->
<div id="app">
<todo>
<todo-title slot="todo-title" :title="title"></todo-title>
<todo-items slot="todo-items" v-for="item in todoItems" :item="item"></todo-items>
</todo>
</div>
<!-- 导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
//slot:插槽插入数据
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'],
template: ' <li>{{item}}</li>'
});
var vm = new Vue({
el: "#app", //通过element元素绑定id为app的模块
data: {
title: "hello,Vue!",
todoItems: ['Java', 'Python', 'Linux']
},
});
</script>
</body>
</html>
自定义事件分发
由于自定义的插槽组件的作用域仅仅是插槽,但是数据位于Vue的对象内,插槽里的按钮作用不到。因此通过自定义标签绑定Vue对象里的方法和值,然后传入自定义的插槽组件中
在自定义标签绑定Vue对象的方法时,v-on:自定义方法名=“Vue对象方法名”,进行方法和参数的传递。通过this.$emit(‘自定义方法名’,‘参数’);接收完成绑定。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--View层 模版Template-->
<div id="app">
<todo>
<todo-title slot="todo-title" :title="title"></todo-title>
<todo-items slot="todo-items" v-for="(item,index) in todoItems" :item="item" :index="index"
v-on:remove="removeItems(index)" ></todo-items>
</todo>
</div>
<!-- 导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
//slot:插槽插入数据
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}}----{{item}}<button @click="remove">Delete</button></li>',
//只能绑定当前组件的方法,而拿不到vm对象的方法
methods: {
remove: function (index) {
//自定义事件分发
this.$emit('remove', index);
alert("Complete delete");
}
}
});
var vm = new Vue({
el: "#app", //通过element元素绑定id为app的模块
data: {
title: "hello,Vue!",
todoItems: ['Java', 'Python', 'Linux']
},
methods: {
removeItems: function (index) {
console.log("删除了:" + this.todoItems[index])
//splice(index,int,"String","String");index:下标,int:删除当前下标下多少个元素,String:添加的项目
this.todoItems.splice(index, 1); //一次删除一个元素
}
}
});
</script>
</body>
</html>
三、Vue项目
所有元素必须包含在标签中,即根节点下
vuec-cli是官方提供的脚手架,用于快速生成一个vue项目模版
3.1、创建Vue项目
# 进入目录工程
#安装vue-router
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
3.2、Npm命令解释
npm install moduleName:安装模块到项目目录下
npm install -g moduleName:-g 的意思是将模块安装到全局,具体到磁盘中哪个位置看 npm config ls 中的 prefix位置
npm install -save moduleName:–save的意思是将模块安装到项目目录下,并在package文件的dependencies节点写入依赖,-S为该命令缩写
npm install -save-dev moduleName:–save-dev的意思是将模块安装到项目目录下,并在package文件的devDependencies节点写入依赖,-D为该命令缩写
3.3、Router路由配置
小问题:在项目搭建中遇到了个小问题,sass-loader的版本是7.3.1,node-sass的版本是4不兼容,npm uninstall node-sass
卸载node-sass,npm install sass@1.26.5 --save-dev
安装1.26.5版本即可(因为nodejs版本是16所以sass加载器版本必须在7以上)
配置步骤:
- 检查项目node model中是否存在vue-router
- 新建router文件夹,用来存放路由,引入路由之后必须通过
Vue.use(VueRouter);
安装
例:新建一个index.js的路由
注意:routes数组里每条路由的path路径是访问路径,即在浏览器的搜索框里输入path跳转至对应页面,绝对路径已经在import导入时与组件绑定,因此path无关紧要
import Vue from 'vue'
import Router from 'vue-router'
import Main from '../views/Main.vue'
import Login from '../views/Login.vue'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/login',
component: Login
}, {
path: '/main',
component: Main
}
]
})
- 在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)
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
render: h => h(App) /* ElementUI的官方配置 */
})
- 定义组件
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">
<!--插入的地方-->
<!-- name:组件名,通过params传递参数 vm双向绑定 -->
<router-link :to="{name:'profile', 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 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: #5ba1fd;
color: #333;
line-height: 60px;
}
.el-aside {
color: #333;
}
</style>
Login登录:
<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) {
// 为表单绑定验证功能
//通过$refs引用数据
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 hsl(220, 4%, 58%);
}
.login-title {
text-align: center;
margin: 0 auto 40px auto;
color: #303133;
}
</style>
- 在App.vue主入口中使用路由
<template>
<div id="app">
<router-link to="/login">login</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
<style>
</style>
3.4、嵌套路由
嵌套路由又称子路由,即多层嵌套的组件组合而成,URL中各段状态路径也按某种结构对应嵌套的各层组件
在路由中import导入组件后,在需要嵌套的路由下添加children
属性,配置子路由方式和普通路由一致
{
path: '/main',
component: Main,
// 嵌套路由
children: [
{path: '/user/profile/:id',
name: 'profile',
component: UProfile},
{path: '/user/list', component: UList}
]
}
例子中通过路由给页面传递参数:改变了to的值,将其作为对象使用需要双向绑定,并且里面的属性必须和路由中定义的属性名对应
<el-menu-item index="1-1">
<!--插入的地方-->
<!-- name:组件名,通过params传递参数 vm双向绑定 -->
<router-link :to="{name:'profile', params:{id:1}}">个人信息</router-link>
</el-menu-item>
嵌套路由的页面:
**比较接收参数的方式!**此处通过route取
<template>
<div>
<h1>个人信息</h1>
{{$route.params.id}}
</div>
</template>
<script>
export default {
name: 'profile'
}
</script>
<template>
<h1>用户列表</h1>
</template>
<script>
export default {
name: 'list'
}
</script>
3.5、参数传递
通过props解耦
将路由中的props属性设为true
此处遇到小问题:配置路由时props位于conponent上方报错
index.js:
import Vue from 'vue'
import Router from 'vue-router'
import Main from '../views/Main.vue'
import Login from '../views/Login.vue'
import UList from '../views/user/List.vue'
import UProfile from '../views/user/Profile.vue'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/login',
component: Login
}, {
path: '/main',
component: Main,
// 嵌套路由
children: [
{path: '/user/profile/:id',
name: 'profile',
component: UProfile,
props: true},
{path: '/user/list', component: UList}
]
}
]
})
profile:通过props组件
<template>
<div>
<h1>个人信息</h1>
<!-- {{$route.params.id}} -->
{{id}}
</div>
</template>
<script>
export default {
props: ['id'],
name: 'profile'
}
</script>
3.6、重定向
重定向即添加一个新的路由路径,增加redirect属性指定一个需要跳转的路径,再页面中添加互动标签导入此路由即可
import Vue from 'vue'
import Router from 'vue-router'
import Main from '../views/Main.vue'
import Login from '../views/Login.vue'
import UList from '../views/user/List.vue'
import UProfile from '../views/user/Profile.vue'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/login',
component: Login
}, {
path: '/main',
component: Main,
// 嵌套路由
children: [
{path: '/user/profile/:id',
name: 'profile',
component: UProfile,
props: true},
{path: '/user/list', component: UList}
]
},
{
path: '/gohome',
redirect: '/main'
}
]
})
Main.vue:
<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">
<!--插入的地方-->
<!-- name:组件名,通过params传递参数 vm双向绑定 -->
<router-link :to="{name:'profile', 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-menu-item index="1-3">
<!--插入的地方-->
<router-link to="/gohome">主界面</router-link>
</el-menu-item>
</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: #5ba1fd;
color: #333;
line-height: 60px;
}
.el-aside {
color: #333;
}
</style>
解决url总有个井号的问题
路由模式有两种
- hash:路由路径带#符号,如 http://localhost/#/login
- history:路径不带井号,如http://localhost/login
修改路由配置,例子修改的是index:
export default new Router({
mode: 'history',
routes: [
]
})
3.7、404界面
当访问访问不到的路径时,弹出404页面,路径用 * 表示,即能访问到的路径直接进入,访问不到一律走404
NotFound界面:
<template>
<div>
<h1>404,你的页面走丢了</h1>
</div>
</template>
<script>
export default {
name: 'NotFound'
}
</script>
index路由配置:
{
path: '*',
component: NotFound
}
3.8、路由钩子和异步请求
vue生命周期
beforeRouteEnter
:在进入路由前执行
beforeRouteLeave
:在离开路由前执行
export default {
props: ['id'],
name: 'profile',
// 过滤器
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是组件实例
通过next获取数据:
-
配置main.js安装axios,并在static/mock下建立伪数据(参考之前网络通信)
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' import axios from 'axios' import VueAxios from 'vue-axios' Vue.use(router) Vue.use(ElementUI) Vue.use(VueAxios, axios) /* eslint-disable no-new */ new Vue({ el: '#app', router, render: h => h(App) /* ElementUI的官方配置 */ })
-
在next方法中编写对象实例,调用本对象的方法,并在方法中编写获取数据的方法,利用控制台输出response对象
export default { props: ['id'], name: 'profile', // 过滤器 beforeRouteEnter: (to, from, next) => { console.log('进入之前') next(vm => { vm.getData() }) }, beforeRouteLeave: (to, from, next) => { console.log('离开') next() }, methods: { getData: function () { this.axios({ method: 'get', url: 'http://localhost:8080/static/mock/data.json' }).then(function (response) { console.log(response) }) } } }