前言:
学习B站UP主狂神说视频笔记整理视频链接
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式JavaScript框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用(SPA)提供驱动
官网:vue.js
MVVM源自于经典的 MVC (Model-View-Controller)模式。MVVM的核心是ViewModel层,负责转换Model 中的数据对象来让数据变得更容易管理和使用,其作用如下:
上图描述了MVVM一个基本结构,看到了什么,是不是发现比MVC架构中多了一个ViewModel,没错,就是这个ViewModel,他是MVVM相对于MVC改进的核心思想。在开发过程中,由于需求的变更或添加,项目的复杂度越来越高,代码量越来越大,此时我们会发现MVC维护起来有些吃力,首先被人吐槽的最多的就是MVC的简写变成了Massive-View-Controller(意为沉重的Controller)
由于Controller主要用来处理各种逻辑和数据转化,复杂业务逻辑界面的Controller非常庞大,维护困难,所以有人想到把Controller的数据和逻辑处理部分从中抽离出来,用一个专门的对象去管理,这个对象就是ViewModel,是Model和Controller之间的一座桥梁。当人们去尝试这种方式时,发现Controller中的代码变得非常少,变得易于测试和维护,只需要Controller和ViewModel做数据绑定即可,这也就催生了MVVM的热潮。
在MVVM架构中,是不允许数据和视图直接通信的,只能通过ViewModel来通信,而ViewModel就是定义了一个 Observer观察者
至此,我们就明白了,Vue.js 就是一个MVVM的实现者,他的核心就是实现了DOM监听与数据绑定
轻量级,体积小是一个重要指标。Vue.js 压缩后有只有20多kb (Angular压缩后56kb+,React压缩后44kb+)
移动优先。更适合移动端,比如移动端的Touch事件易上手,学习曲线平稳,文档齐全
吸取了Angular (模块化)和React(虚拟DOM)的长处,并拥有自己独特的功能,如:计算属性
开源,社区活跃度高
…
IDEA中可以安装Vue插件
注意:Vue 不支持 IE8 及以下版本,因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性。但它支持所有兼容 ECMAScript 5 的浏览器。
引入对于制作原型或学习,你可以这样使用最新版本:
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
对于生产环境,我们推荐链接到一个明确的版本号和构建文件,以避免新版本造成的不可预期的破坏:
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hellovuetitle>
head>
<body>
<div id="app">
{
{ message }}
div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script>
<script>
var app = new Vue({
el: '#app',
/*model: 数据*/
data: {
message: 'Hello Vue!'
}
})
script>
body>
html>
我们已经成功创建了第一个 Vue 应用!看起来这跟渲染一个字符串模板非常类似,但是 Vue 在背后做了大量工作。现在数据和 DOM 已经被建立了关联,所有东西都是响应式的。我们要怎么确认呢?打开你的浏览器的 JavaScript 控制台 (就在这个页面打开),并修改 app.message
的值,你将看到上例相应地更新。
注意我们不再和 HTML 直接交互了。一个 Vue 应用会将其挂载到一个 DOM 元素上 (对于这个例子是 #app
) 然后对其进行完全控制。那个 HTML 是我们的入口,但其余都会发生在新创建的 Vue 实例内部。
除了文本插值,我们还可以像这样来绑定元素 attribute
:
<div id="app-2">
<span v-bind:title="message">
鼠标悬停几秒钟查看此处动态绑定的提示信息!
span>
div>
var app2 = new Vue({
el: '#app-2',
data: {
message: '页面加载于 ' + new Date().toLocaleString()
}
})
鼠标悬停几秒钟查看此处动态绑定的提示信息!
这里我们遇到了一点新东西。你看到的 v-bind attribute
被称为指令。指令带有前缀 v-
,以表示它们是 Vue 提供的特殊 attribute
。可能你已经猜到了,它们会在渲染的 DOM 上应用特殊的响应式行为。在这里,该指令的意思是:“将这个元素节点的 title attribute
和 Vue 实例的 message property
保持一致”。
如果你再次打开浏览器的 JavaScript 控制台,输入 app2.message = '新消息'
,就会再一次看到这个绑定了 title attribute
的 HTML 已经进行了更新。
控制切换一个元素是否显示也相当简单:
<div id="app-3">
<p v-if="seen">现在你看到我了p>
div>
var app3 = new Vue({
el: '#app-3',
data: {
seen: true
}
})
现在你看到我了
<div id="app">
<h1 v-if="ok">YESh1>
<h2 v-else>NOh2>
div>
let vue = new Vue({
el: "#app",
data: {
ok: true
}
});
<div id="app1">
<h1 v-if="type==='A'">Ah1>
<h1 v-else-if="type==='B'">Bh1>
<h1 v-else="type==='C'">Ch1>
div>
new Vue({
el: "#app1",
data: {
type: 'B'
}
});
<div id="app2">
<h1 v-for="item in items">{
{item.message}}h1>
div>
new Vue({
el: "#app2",
data: {
items: [
{
message: "hello"},
{
message: "word"}
]
}
});
为了让用户和你的应用进行交互,我们可以用 v-on
指令添加一个事件监听器,通过它调用在 Vue 实例中定义的方法:
<div id="example-2">
<button v-on:click="sat">Greetbutton>
div>
new Vue({
el: "#example-2",
data: {
message: "helloword"},
methods: {
//方法必须定义在vue内的methods中
sat: function () {
alert(this.message);
}
}
})
Vue.js 是一个 MVVM框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化。 这也算是Vue.js精髓之处了。
值得注意的是,我们所说的数据双向绑定,一定是对于UI控件来说的,非UI控件不会涉及到数据双向绑定。单向数据绑定是使用状态管理工具的前提。如果我们使用vuex,那么数据流也是单项的,这时就会和双向数据绑定有冲突。
在vue.js 中,如果使用vuex,实际上数据还是单向的,之所以说是数读双向绑定,这过用的uI控件来说,对于我们处理表中,vue.js双向数据绑定用起来特别舒服。即两者并不互斥,在全局性数据流使用单项,方便跟踪;同部件数据流使用双向,简单易操作。
你可以用v-model
指令在表单 、
及元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但
v-model
本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
注意:
v-model
会忽略所有表单元素的value,checked、selected
特性的初始值而总是将Vue实例的数据作为数据来源。你应该通过JavaScript在组件的data选项中声明初始值!
<div id="example-2">
输入文本 <input type="text" name="username" id="input1" v-model="message">{
{message}}
div>
new Vue({
el: "#example-2",
data: {
message: "123"
}
})
<div id="example-2">
多行文本: <textarea v-model="message" placeholder="add multiple lines">textarea>{
{message}}
div>
new Vue({
el: "#example-2",
data: {
message: ""
}
})
<div id="example-2">
单选框:
<input type="radio" name="sex" value="男" v-model="message">男
<input type="radio" name="sex" value="女" v-model="message">女
{
{message}}
div>
new Vue({
el: "#example-2",
data: {
message: ""
}
})
如果 v-model
表达式的初始值未能匹配任何选项, 元素将被渲染为“未选中”状态。在 iOS 中,这会使用户无法选择第一个选项。因为这样的情况下,iOS 不会触发
change
事件。因此,更推荐像下面这样提供一个值为空的禁用选项。
<div id="example-2">
<select v-model="message">
<option disabled value="">请选择option>
<option>Aoption>
<option>Boption>
<option>Coption>
select>
<span>{
{message}}span>
div>
new Vue({
el: "#example-2",
data: {
message: ""
}
})
组件是可复用的 vue实例,说白了就是一组可以重复使用的模板,跟JSTL的自定义标签、Thymeleaf的 th:fragment
等框架有着异曲同工之妙。通常一个应用会以一棵嵌套的组件树的形式来组织:
例如,你可能会有页头、侧边栏、内容区等组件,每个组件又包含了其它的像导航链接、博文之类的组件。
为了能在模板中使用,这些组件必须先注册以便 Vue 能够识别。这里有两种组件的注册类型:全局注册和局部注册。至此,我们的组件都只是通过 Vue.component
全局注册的:
Vue.component('my-component-name', {
// ... options ...
})
定义一个组件:
Vue.component('one',{
template: 'JavaEE '
});
组件是可复用的 Vue 实例,且带有一个名字:在这个例子中是
。我们可以在一个通过 new Vue
创建的 Vue 根实例中,把这个组件作为自定义元素来使用:
<div id="example-2">
<li>JavaSEli>
<one>one>
div>
new Vue({
el: "#example-2"
});
在组件中无法直接取到数据,需要通过Prop
<div id="example-2">
<one v-for="item in items" v-bind:qin="item">one>
div>
Vue.component('one',{
/*组件中传递数据 props*/
props: ['qin'],
template: '{
{qin}} '
});
new Vue({
el: "#example-2",
data: {
items: ["Java","Javascript","C++"]
}
});
说明:
v-for="item in items"
:遍历Vue实例中定义的名为 items
的数组,并创建同等数量的组件
v-bind:qin="item"
︰将遍历的 item项绑定到组件中 props定义的名为 item 属性上; =号左边的item为props定义的属性名,右边的为item in items
中遍历的item 项的值
在vue.js中我们使用
元素作为承载分发内容的出口,作者称其为插槽,可以应用在组合组件的场景中,插槽是组件的一种:
<div id="app">
<todo>
<todo-title slot="todo-title" v-bind:title="username">todo-title>
<todo-times slot="todo-times" v-for="todoitem in todoitems" v-bind:items="todoitem">todo-times>
todo>
div>
<script>
/*插槽是组件的一种*/
Vue.component("todo",{
template: ''+
' '+
''
+
' '+
''+
''
})
Vue.component("todo-title",{
props: ["title"],
template: '{
{title}}'
})
Vue.component("todo-times",{
props: ["items"],
template: '{
{items}} '
})
new Vue({
el: "#app",
data: {
username: "秦疆",
todoitems: ["狂神说Java","狂神说前端"]
}
});
</script>
在
使用name
属性关联其他组件
通过以上代码不难发现,数据项在Vue的实例中,但删除操作要在组件中完成,那么组件如何才能删除Vue 实例中的数据呢?此时就涉及到参数传递与事件分发了,Vue为我们提供了自定义事件的功能很好的帮助我们解决了这个问题;使用this.$emit('自定义事件名',参数)
,操作过程如下:
for循环不仅可以遍历出数组元素,还可以遍历出数组下标
<div id="app">
<todo>
<todo-title slot="todo-title" v-bind:title="username">todo-title>
<todo-times slot="todo-times" v-for="(todoitem,index) in todoitems"
v-bind:items="todoitem" v-bind:index="index" v-on:remove="removeitems(index)" v-bind:key="index">todo-times>
todo>
div>
/*插槽是组件的一种*/
Vue.component("todo",{
template: ''+
' '+
''
+
' '+
''+
''
})
Vue.component("todo-title",{
props: ["title"],
template: '{
{title}}'
})
/*props获取到数组元素与数组下标*/
Vue.component("todo-times",{
props: ["items","index"],
/*绑定点击事件 方法指向组件中methods-remove*/
template: '{
{index}}--{
{items}} ',
methods: {
remove: function (index) {
alert(index)
/* 参数一: 自定义事件名 参数二: 数组下标 方法指向页面中的自定义事件 通过自定义事件调用VUe实例中的方法*/
this.$emit('remove',index);
}
}
})
var em= new Vue({
el: "#app",
data: {
username: "秦疆",
todoitems: ["狂神说Java","狂神说前端","狂神说Liunx"]
},
methods: {
removeitems: function (index) {
//js中移除数组元素的方法
this.todoitems.splice(index,1);
}
}
});
Axios是一个开源的可以用在浏览器端和Nodes的异步通信框架,她的主要作用就是实现 AJAX异步通信,其功能特点如下:
XMLHttpRequests
由于Vue.js是一个视图层框架并且作者(尤雨溪)严格准守SoC (关注度分离原则),所以Vue. js并不包含AJAX的通信功能,为了解决通信问题,作者单独开发了一个名为vue-resource的插件,不过在进入2.0版本以后停止了对该插件的维护并推荐了Axios框架。少用jQuery,因为它操作Dom太频繁!
准备一段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/"
}
]
}
在html中导入AXIOS CDN
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
编写代码
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<div id="vue">
<p>{
{info.name}}p>
<p>{
{info.links}}p>
<a v-bind:href="info.url">点击a>
div>
<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>
new Vue({
el: "#vue",
//data: 属性 使用钩子函数 data()是个方法
data(){
return{
// 请求的参数 必须跟JSON字符串格式一样
info: {
name: null,
url: null,
page: null,
isNonProfit: null,
address: {
street: null,
city: null,
country: null
},
links: [
{
name: null,url:null}
]
}
}
},
mounted(){
//钩子函数 ES6新特性
axios.get("data.json").then(response=>(this.info=response.data));
}
});
script>
body>
html>
Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载 DOM、渲染→更新→渲染、卸载等一系列过程,我们称这是Vue 的生命周期。通俗说就是Vue 实例从创建到销毁的过程,就是生命周期。
在Vue 的整个生命周期中,它提供了一系列的事件,可以让我们在事件触发时注册JS方法,可以让我们用自己注册的JS方法控制整个大局,在这些事件响应方法中的this直接指向的是Vue的实例。
计算属性的重点突出在属性两个字上(属性是名词),首先它是个属性其次这个属性有计算的能力(计算是动词),这里的计算就是个函数;简单点说,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性),仅此而已;可以想象为缓存!
上代码:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性title>
head>
<body>
<div id="app">
<p>{
{currentTime2}}p>
<p>{
{currentTime1()}}p>
div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js">script>
<script>
new Vue({
el: "#app",
data: {
message: "helloword"
},
methods: {
currentTime1: function () {
return Date.now();//返回一个时间戳
}
},
computed: {
//计算属性 前提methods与computed 方法不能重名 重名之后只会调用methods的方法
currentTime2: function () {
return Date.now();//返回一个时间戳
}
}
});
script>
body>
html>
结论:
调用方法时,每次都需要进行计算,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?此时就可以考虑将这个结果缓存起来,采用计算属性可以很方便的做到这一点,计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销;
vue-cli官方提供的一个脚手架,用于快速生成一个vue的项目模板;
预先定义好的目录结构及基础代码,就好比咱们在创建Maven项目时可以选择创建一个骨架项目,这个骨架项目就是脚手架,我们的开发更加的快速;
主要功能:
确认Node.js安装成功
CMD输入
node -v
查看是否正确打印版本号信息即可
CMD输入npm -v
查看是否正确打印版本号信息即可
这个npm,就是一个软件包管理工具,就和linux下的apt软件安装差不多!
# -g就是全局安装
npm install cnpm -g
# 或使用如下解决速度慢问题
npm install --registry=https://registry.npm.taobao.org
cnpm install vue-cli -g
# 测试是否安装成功
# 查看查看可以基于哪些模板创建vue应用程序,通常我们选择 webpack
vue list
1.创建一个Vue项目,我们随便建立一个空的文件夹在电脑上,我这里在D盘下新建一个目录D:\Item\WorkSpace
2.创建一个基于webpack模板的vue应用程序
#这里的myvue是项日名你,以恨却自已的需求起名
vue init webpack myvue
进入项目目录下,我这里是D:\Item\WorkSpace\myvue
npm install
npm run dev
由于vue的SOC原则,所以vue本身并不具备页面跳转
Vue Router是Vue.js官方的路由管理器。它和Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:
在vue-cli快速上手中创建的项目下安装vue-route
安装完成后会在node_modules目录下新增vue-route的相关依赖,相当于导入maven依赖
# 安装vue-route
npm install vue-router --save-dev
<template>
<h1>内容页</h1>
</template>
<script>
export default {
name: "Context"
}
</script>
<style scoped>
</style>
import Vue from 'vue'
import VueRouter from "vue-router"; //导入路由
import Context from '../components/Context' //导入相关页面
//vue中需要显示声明使用VueRouter 安装路由
Vue.use(VueRouter);
//配置导出路由
export default new VueRouter({
//数组 可以配置多个页面
routes: [
{
//路由路径 相当于Java中的@RequestMapping
path: '/content',
//路由名字
name: "context",
//跳转的组件
component: Context
}
]
})
import Vue from 'vue'
import App from './App'
import router from './router' //自动扫描包里面名字为index的路由配置
Vue.config.productionTip = false
new Vue({
el: '#app',
//配置路由
router,
components: {
App },
template: ' '
})
<template>
<div id="app">
<router-link to="/content">内容页router-link>
<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>
# CMD命令行执行
npm run dev
参考本文-Vue实战-嵌套路由
参考本文-Vue实战-参数传递
重定向也是通过 routes
配置来完成,下面例子是从 /a 重定向到 /b:
const router = new VueRouter({
routes: [
{
path: '/a', redirect: '/b' }
]
})
重定向的目标也可以是一个命名的路由:
const router = new VueRouter({
routes: [
{
path: '/a', redirect: {
name: 'foo' }}
]
})
当我们输入一些不存在的路径时会报404,在路由中也可以实现
编写一个404页面
<template>
<div>
<h1>404h1>
<h2>页面走丢了h2>
div>
template>
<script>
export default {
name: "Notfaund"
}
script>
<style scoped>
style>
在路由配置index.js
中配置
{
//404 匹配不到的路径会走以下页面
path: "*",
component: Notfaund
}
vue-router 默认 hash
模式 —— 使用 URL 的 hash
来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。
URL:localhost:8080/#/Main
如果不想要很丑的 hash
,我们可以用路由的 history
模式,这种模式充分利用 history.pushState
API 来完成 URL 跳转而无须重新加载页面。
const router = new VueRouter({
mode: 'history',
routes: [...]
})
本质上,webpack 是一个现代JavaScript应用程序的静态模块打包器(module bundler)。当webpack处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个bundle.
Webpack 是当下最热门的前端资源模块化管理和打包工具,它可以将许多松散耦合的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分离,等到实际需要时再异步加载。通过loader转换,任何形式的资源都可以当做模块,比如CommonsJS、AMD、ES6、CSs、JSON、CoffeeScript、LESS等;
<script src = " module3. js "></scirpt>
<script src = " module4 .js "> < / scirpt>
这是最原始的JavaScript文件加载方式,如果把每一个文件看做是一个模块,那么他们的接口通常是暴露在全局作用域下,也就是定义在 window
对象中,不同模块的调用都是一个作用域。
这种原始的加载方式暴露了一些显而易见的弊端:
的书写顺序进行加载开发人员必须主观- 解决模块和代码库的依赖关系服务器端的NodeJS遵循CommonsJS规范,该规范核心思想是允许模块通过require
方法来同步加载所需依赖的其它模块,然后通过exports
或 module.exports
来导出需要暴露的接口。
require ( "module ");
require( " ../module.js " ) ;
export .dostuff = function( ) {
};
module.exports = somevalue ;
优点:
缺点:
实现:
…
…
EcmaScript6标准增加了JavaScript语言层面的模块体系定义。ES6模块的设计思想,是尽量静态化,使编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonsJS和AMD模块,都只能在运行时确定这些东西。
import "jquery " ;
export funetion dostuff() {
}
module "localMadule” {
}
优点
缺点
WebPack 是一款模块加载器兼打包工具,它能把各种资源,如JS、JSX、ES6、SASS、LESS.图片等都作为模块来处理和使用。
安装:
npm install webpack -g
npm install webpack-cli -g
创建webpack.config.js
配置文件
新建目录webpackTest
测试webpack
编写hello.js
//暴露一个方法
exports.Hello=function () {
alert("helloword!");
}
编写main.js
var hello=require("./hello");
hello.Hello();
编写webpack.config.js
配置文件
module.exports={
/*找到程序的入口*/
entry: './webpackTest/main.js',
output: {
/*生成打包后的文件*/
filename: './js/bundle.js'
}
};
cmd下执行webpack
打包
# 使用以下命令可以实现热部署 代码一旦改变就会重新打包
webpack --watch
Vue结合ElementUI
Demo项目
vue init webpack hello
与之前一样 一路No即可
## 安装vue-router路由
npm install vue-router --save-dev
## 安装Element
npm i element-ui -S
## 安装运行环境
npm install
## 安装SASS加载器
npm install sass-loader node-sass --sass-dev
<template>
<div id="loginapp">
<h3>用户登录h3>
<el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
<el-form-item label="密码" prop="pass">
<el-input type="password" v-model="ruleForm.pass" autocomplete="off">el-input>
el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input type="password" v-model="ruleForm.checkPass" autocomplete="off">el-input>
el-form-item>
<el-form-item label="年龄" prop="age">
<el-input v-model.number="ruleForm.age">el-input>
el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">提交el-button>
<el-button @click="resetForm('ruleForm')">重置el-button>
el-form-item>
el-form>
div>
template>
<script>
export default {
name: "Login",
data() {
var checkAge = (rule, value, callback) => {
if (!value) {
return callback(new Error('年龄不能为空'));
}
setTimeout(() => {
if (!Number.isInteger(value)) {
callback(new Error('请输入数字值'));
} else {
if (value < 18) {
callback(new Error('必须年满18岁'));
} else {
callback();
}
}
}, 1000);
};
var validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'));
} else {
if (this.ruleForm.checkPass !== '') {
this.$refs.ruleForm.validateField('checkPass');
}
callback();
}
};
var validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.ruleForm.pass) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
ruleForm: {
pass: '',
checkPass: '',
age: ''
},
rules: {
pass: [
{
validator: validatePass, trigger: 'blur' }
],
checkPass: [
{
validator: validatePass2, trigger: 'blur' }
],
age: [
{
validator: checkAge, trigger: 'blur' }
]
}
};
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
console.log(valid);
alert('submit!');
//使用vue-router路由到指定页面
this.$router.push('/Main');
} else {
console.log('error submit!!');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
}
script>
<style scoped>
#loginapp{
width: 500px;
height: 300px;
}
style>
<template>
<div>
<Login/>
div>
template>
<script>
import Login from './Login';
export default {
name: "Main",
components: {
Login
}
}
script>
<style scoped>
style>
import Vue from 'vue';
import VueRouter from "vue-router";//导入路由
import Login from '../views/Login';//导入登录页面
import Main from '../views/Main';//导入Main
Vue.use(VueRouter);//显示声明VueRouter
//配置路由转发
export default new VueRouter({
routes: [
{
path: '/Login',
name: 'Login',
component: Login
},
{
path: '/Main',
name: 'Main',
component: Main
}
]
})
import Vue from 'vue'
import App from './App'
import router from './router' //自动扫描路由
import ElementUI from 'element-ui'; //导入Elment-UI
import 'element-ui/lib/theme-chalk/index.css';
Vue.config.productionTip = false
Vue.use(router);
Vue.use(ElementUI);
/* eslint-disable no-new */
new Vue({
el: '#app',
router,//配置路由
render: h => h(App) //配置ElmentUI
})
<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>
在一个路径下包含其他子路径
如:localhost:8080/Mian/user/list
import Vue from 'vue';
import VueRouter from "vue-router";//导入路由
import Login from '../views/Login';//导入登录页面
import Main from '../views/Main';//导入Main
import UserProfile from "../views/user/Profile";
import UserList from "../views/user/UserList";
Vue.use(VueRouter);//显示声明VueRouter
//配置路由转发
export default new VueRouter({
routes: [
{
path: '/Login',
name: 'Login',
component: Login
},
{
path: '/Main',
name: 'Main',
component: Main,
//嵌套路由
children: [
{
path: '/user/list',component: UserList},
{
path: 'user/profile',component: UserProfile}
]
}
]
})
<template>
<div>
<el-row class="tac">
<el-col :span="12" id="fromelco">
<h5>默认颜色h5>
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose">
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location">i>
<span>导航一span>
template>
<el-menu-item-group>
<template slot="title">分组一template>
<el-menu-item index="1-1"> <router-link to="/user/list">个人信息一router-link> el-menu-item>
<el-menu-item index="1-2"><router-link to="/user/profile">个人信息页二router-link>el-menu-item>
el-menu-item-group>
el-submenu>
<el-menu-item index="2">
<i class="el-icon-menu">i>
<span slot="title">导航二span>
el-menu-item>
<el-menu-item index="3" disabled>
<i class="el-icon-document">i>
<span slot="title">导航三span>
el-menu-item>
<el-menu-item index="4">
<i class="el-icon-setting">i>
<span slot="title">导航四span>
el-menu-item>
el-menu>
el-col>
<el-main>
<router-view/>
el-main>
el-row>
div>
template>
<script>
import Login from './Login';
export default {
name: "Main",
components: {
Login
}
}
script>
<style scoped>
#fromelco{
width: 250px;
}
style>
页面跳转时可以携带一些参数,完成参数传递有两种方式可以实现
方式一:
<el-menu-item-group>
<template slot="title">分组一template>
<el-menu-item index="1-1"> <router-link v-bind:to="{name: 'userList' ,params: {id: 1}}">个人信息一router-link> el-menu-item>
<el-menu-item index="1-2"><router-link to="/user/profile">个人信息页二router-link>el-menu-item>
el-menu-item-group>
更改index.js
路由配置,在路径下加入需要传递的参数名
编写接收参数的页面UserList.vue
方式二:
更改index.js
路由配置,设置props
为true
编写接收参数的页面UserList.vue
,新增props
beforeRouteEnter
:进入路由之前执行
beforeRouteLeave
:进入路由之后执行
修改UserList.vue
,添加以下代码
export default {
props: ['id'],
name: "UserList",
beforeRouteEnter: (to,from,next)=>{
console.log("进入路由之前执行")
next();//入下一方法 不写这个程序会一直等待
},
beforeRouteLeave: (to,from,next)=>{
console.log("进入路由之后执行");
next();//进入下一方法
}
}
参数说明:
在钩子函数中使用异步请求:
npm install --save axios vue-axios
main.js
中配置Axiosimport Vue from 'vue'
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(VueAxios, axios)
static
目录下(静态资源都得放在static目录下才能够访问){
"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/"
}
]
}
<template>
<div>
<h1>{
{username}}h1>
<h1>{
{info.name}}h1>
<h1>{
{info.url}}h1>
<h1 v-for=" add in info.address">{
{add}}h1>
<h1 v-for=" lik in info.links">{
{lik.name}}h1>
<h1 v-for=" lik in info.links">{
{lik.url}}h1>
div>
template>
<script>
export default {
props: ['id'],
name: "UserList",
//data: 属性 使用钩子函数 data()是个方法
data(){
return{
// 请求的参数 必须跟JSON字符串格式一样
info: {
name: null,
url: null,
page: null,
isNonProfit: null,
address: {
street: null,
city: null,
country: null
},
links: [
{
name: null,url:null}
]
},
username: '秦疆'
}
},
beforeRouteEnter: (to,from,next)=>{
console.log("进入路由之前执行")
next(vm=>{
vm.getData();//进入路由之前执行getData方法
});
},
beforeRouteLeave: (to,from,next)=>{
console.log("进入路由之后执行");
next();//进入下一方法
},
methods: {
getData: function () {
//静态资源存放在项目的static目录下 可以通过路径直接访问到
this.axios.get('http://localhost:8080/static/mork/kuang.json').then(response=>(this.info=response.data));
}
}
}
script>
<style scoped>
style>