网络通信 : axios
页面跳转 : vue-router
状态管理:vuex
Vue-UI : ICE , Element UI
vue官方文档
https://cn.vuejs.org/v2/guide/
Vue (读音/vju/, 类似于view)是一套用于构建用户界面的渐进式框架,发布于2014年2月。
与其它大型框架不同的是,Vue被设计为可以自底向上逐层应用。
Vue的核心库只关注视图层,不仅易于上手,还便于与第三方库(如: vue-router: 跳转,vue-resource: 通信,vuex:管理)或既有项目整合。
MVVM是Model-View-ViewModel的简写。它本质上就是MVC (Model-View- Controller)的改进版。即模型-视图-视图模型。
总结:在MVVM的框架下视图和模型是不能直接通信的。它们通过ViewModel来通信,ViewModel通常要实现一个observer观察者,当数据发生变化,ViewModel能够监听到数据的这种变化,然后通知到对应的视图做自动更新,而当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动,这实际上就实现了数据的双向绑定。并且MVVM中的View 和 ViewModel可以互相通信。
MVVM模式和MVC模式一样,主要目的是分离视图(View)和模型(Model)。
有几大好处:
Vue.js 就是一个MVVM的实现者,他的核心就是实现了DOM监听与数据绑定
v-bind
现在数据和DOM已经被建立了关联,所有的东西都是响应式的。
我们在控制台操作对象的属性,界面可以实时更新。我们可以使用v-bind
来绑定元素属性!
<!DOCTYPE>
<html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>狂神说Java</p>
<!--view层 模板-->
<div id="app">
<span v-bind:title="message">鼠标悬停几秒钟查看此处动态绑定的提示信息!</span>
</div>
</body>
<!--导入js-->
<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,vue"
}
})
</script>
</html>
v-if
v-else
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>狂神说Java</p>
<!--view层 模板-->
<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>
<!--导入js-->
<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: "A"
}
})
</script>
</html>
v-for
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>狂神说Java</p>
<!--view层 模板-->
<div id="app">
<li v-for="item in items">
姓名:{{item.name}},年龄:{{item.age}}
</li>
</div>
</body>
<!--导入js-->
<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: [
{name: "zhangsan", age: 12},
{name: "lisi", age: 10},
{name: "wangwu", age: 16}
]
}
})
</script>
</html>
v-on
事件绑定<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>狂神说Java</p>
<!--view层 模板-->
<div id="app">
<button v-on:click="sayHi">Click Me</button>
</div>
</body>
<!--导入js-->
<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: "你点我干嘛?"
},
methods: {
//方法必须绑定在Vue的Methods对象中,v-on:事件
sayHi: (function (event) {
alert(this.message)
})
}
})
</script>
</html>
v-model
Vue.js是一个MVVM框架,即数据双向绑定,即当数据发生变化的时候,视图也就发生变化,当视图发生变化的时候,数据也会跟着同步变化。这也算是Vue.js的精髓之处了。
值得注意的是,我们所说的数据双向绑定,一定是对于UI控件来说的,非UI控件不会涉及到数据双向绑定。单向数据绑定是使用状态管理工具的前提。如果我们使用vuex,那么数据流也是单项的,这时就会和双向数据绑定有冲突。
在Vue.js 中,如果使用vuex ,实际上数据还是单向的,之所以说是数据双向绑定,这是用的UI控件来说,对于我们处理表单,Vue.js的双向数据绑定用起来就特别舒服了。即两者并不互斥,在全局性数据流使用单项,方便跟踪;局部性数据流使用双向,简单易操作。
你可以用v-model
指令在表单 <input>
、<textarea>
及<select>
元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但v-model
本质上不过是语法糖。它负责监听户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view层 模板-->
<div id="app">
下拉框:
<select v-model="selected">
<option value="" disabled>-请选择-</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<p>value:{{selected}}</p>
</div>
</body>
<!--导入js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
data: {
selected: ""
}
})
</script>
</html>
组件是可复用的Vue
实例,说白了就是一组可以重复使用的模板,跟JSTL的自定义标签、Thymeleaf的th:fragment
等框架有着异曲同工之妙。通常一个应用会以一棵嵌套的组件树的形式来组织:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view层 模板-->
<div id="app">
<qinjiang v-for="item in items" v-bind:qin="item"></qinjiang>
</div>
</body>
<!--导入js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
Vue.component("qinjiang",{
props: [‘qin‘],
template: ‘<li>{{qin}}</li>‘
})
var vm = new Vue({
el: "#app",
data: {
items: [‘Java‘,‘Python‘,‘Php‘]
}
})
</script>
</html>
Axios是一个开源的可以用在浏览器端和NodeJS
的异步通信框架,她的主要作用就是实现AJAX异步通信,其功能特点如下:
从浏览器中创建XMLHttpRequests
从node.js创建http请求
支持Promise API [JS中链式编程]
拦截请求和响应
转换请求数据和响应数据
取消请求
自动转换JSON数据
客户端支持防御XSRF (跨站请求伪造)
GitHub: https://github.com/ axios/axios
中文文档: http://www.axios-js.com/
由于Vue.js
是一个视图层框架且作者(尤雨溪) 严格准守SoC (关注度分离原则),所以Vue.js
并不包含Ajax的通信功能,为了解决通信问题,作者单独开发了一个名为vue-resource
的插件,不过在进入2.0 版本以后停止了对该插件的维护并推荐了Axios
框架。少用jQuery,因为它操作Dom太频繁 !
模拟Json数据:data.json
{
"name": "weg",
"age": "18",
"sex": "男",
"url":"https://www.baidu.com",
"address": {
"street": "文苑路",
"city": "南京",
"country": "中国"
},
"links": [
{
"name": "bilibili",
"url": "https://www.bilibili.com"
},
{
"name": "baidu",
"url": "https://www.baidu.com"
},
{
"name": "cqh video",
"url": "https://www.4399.com"
}
]
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view层 模板-->
<div id="vue">
{{info}}
</div>
</body>
<!--1.导入vue.js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<!--导入axios-->
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.min.js"></script>
<script>
var vm = new Vue({
el: "#vue",
//data:vm的属性
//data():vm方法
data(){
return{
//请求的返回参数,必须和json字符串一样
info:{
name: null,
age: null,
sex: null,
url: null,
address: {
street: null,
city: null,
country: null
}
}
}
},
//钩子函数,链式编程,ES6新特性
mounted(){
axios.get("../data.json").then(res => (this.info=res.data))
}
})
</script>
</html>
计算属性的重点突出在属性
两个字上(属性是名词),首先它是个属性
其次这个属性有计算
的能力(计算是动词),这里的计算就是个函数;简单点说,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性),仅此而已;可以想象为缓存!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--view层 模板-->
<div id="app">
<div>currentTime1: {{currentTime1()}}</div>
<div>currentTime2: {{currentTime2}}</div>
</div>
</body>
<!--导入js-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.min.js"></script>
<script>
var vm = new Vue({
el: "#app",
methods: {
currentTime1: function () {
return Date.now(); // 返回一个时间戳
}
},
computed: {
//计算属性:methods,computed 方法名不能重名,重名字后,只会调用methods的方法
currentTime2: function () {
this.message;
// 返回一个时间戳
return Date.now();
}
}
})
</script>
结论:
?调用方法时,每次都需要进行计算,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?此时就可以考虑将这个结果缓存起来,采用计算属性可以很方便的做到这一点,计算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销;
在Vue.js中我们使用 元素作为承载分发内容的出口,作者称其为插槽,可以应用在组合组件的场景中;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="app">
<todo>
<todo-title slot="todo-title" v-bind:name="title"></todo-title>
<todo-items slot="todo-items" v-for="item in todoItems" v-bind:item="item"></todo-items>
</todo>
</div>
<!--1.导入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: [‘name‘],
template: ‘<div>{{name}}</div>‘
});
Vue.component("todo-items", {
props: [‘item‘],
template: ‘<li>{{item}}</li>‘
});
let vm = new Vue({
el: "#app",
data: {
//标题
title: "图书馆系列图书",
//列表
todoItems: [‘三国演义‘, ‘红楼梦‘, ‘西游记‘, ‘水浒传‘]
}
});
</script>
</body>
</html>
组件如何才能删除Vue实例中的数据呢?此时就涉及到参数传递与事件分发了,Vue为我们提供了自定义事件的功能很好的帮助我们解决了这个问题;
使用this.$emit (‘自定义事件名’,参数)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="app">
<todo>
<todo-title slot="todo-title" v-bind:name="title"></todo-title>
<todo-items slot="todo-items" v-for="(item,index) in todoItems" v-bind:item="item"
v-bind:index="index" v-on:remove2="removeItems(index)"></todo-items>
</todo>
</div>
<!--1.导入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: [‘name‘],
template: ‘<div>{{name}}</div>‘
});
Vue.component("todo-items", {
props: [‘item‘,‘index‘],
template: ‘<li>{{index}}---{{item}} <button @click="remove1">删除</button></li>‘,
methods: {
remove1: function (index) {
// this.$emit 自定义事件分发
this.$emit(‘remove2‘,index)
}
}
});
let vm = new Vue({
el: "#app",
data: {
//标题
title: "图书馆系列图书",
//列表
todoItems: [‘三国演义‘, ‘红楼梦‘, ‘西游记‘, ‘水浒传‘]
},
methods: {
removeItems: function (index) {
console.log("删除了"+this.todoItems[index]+"OK");
this.todoItems.splice(index,1);
}
}
});
</script>
</body>
</html>
vue-cli 官方提供的一个脚手架,用于快速生成一个 vue 的项目模板;
预先定义好的目录结构及基础代码,就好比咱们在创建 Maven 项目时可以选择创建一个骨架项目,这个骨架项目就是脚手架,我们的开发更加的快速;
主要功能:
Node.js : http://nodejs.cn/download/
安装就无脑下一步就好,安装在自己的环境目录下
Git : https://git-scm.com/downloads
镜像:https://npm.taobao.org/mirrors/git-for-windows/
确认nodejs安装成功:
node -v
,查看是否能够正确打印出版本号即可!npm-v
,查看是否能够正确打印出版本号即可!这个npm,就是一个软件包管理工具,就和linux下的apt软件安装差不多!
npm 是 JavaScript 世界的包管理工具,并且是 Node.js 平台的默认包管理工具。通过 npm 可以安装、共享、分发代码,管理项目依赖关系。
安装 Node.js 淘宝镜像加速器(cnpm)
这样子的话,下载会快很多~
# -g 就是全局安装
npm install cnpm -g
# 若安装失败,则将源npm源换成淘宝镜像
# 因为npm安装插件是从国外服务器下载,受网络影响大
npm config set registry https://registry.npm.taobao.org
# 然后再执行
npm install cnpm -g
#在命令台输入
cnpm install vue-cli -g
#查看是否安装成功
vue list
创建一个Vue项目,我们随便建立一个空的文件夹在电脑上。
# 这里的 myvue 是项目名称,可以根据自己的需求起名
vue init webpack myvue
一路都选择no即可;
初始化并运行
cd myvue
npm install
npm run dev
执行完成后,目录多了很多依赖
Vue Router是Vue.js官方的路由管理器(路径跳转)。
它和Vue.js的核心深度集成,让构建单页面应用变得易如反掌。
包含的功能有:
基于第一个vue-cli进行测试学习;
先查看node_modules中是否存在 vue-router
vue-router 是一个插件包,所以我们还是需要用 npm/cnpm 来进行安装的。打开命令行工具,进入你的项目目录,输入下面命令。
npm install vue-router --save-dev
vue-router
、element-ui
、sass-loader
和node-sass
四个插件# 进入工程目录
cd hello-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
https://element.eleme.cn/#/zh-CN/component/installation
嵌套路由又称子路由,在实际应用中,通常由多层嵌套的组件组合而成。
创建用户信息组件,在 views/user 目录下创建一个名为 Profile.vue 的视图组件;
Profile.vue
<template>
<h1>个人信息</h1>
</template>
<script>
export default {
name: "UserProfile"
}
</script>
在用户列表组件在 views/user 目录下创建一个名为 List.vue 的视图组件;
List.vue
<template>
<h1>用户列表</h1>
</template>
<script>
export default {
name: "UserList"
}
</script>
修改首页视图,我们修改 Main.vue 视图组件,此处使用了 ElementUI 布局容器组件,代码如下:
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">
<!--插入的地方-->
<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="css">
.el-header {
background-color: #B3C0D1;
color: #333;
line-height: 60px;
}
.el-aside {
color: #333;
}
</style>
配置嵌套路由修改 router 目录下的 index.js 路由配置文件,使用children放入main中写入子模块,代码如下
index.js
import Vue from "vue";
import Router from "vue-router";
import Main from "../views/Main";
import Login from "../views/Login";
import UserList from "../views/user/List";
import UserProfile from "../views/user/Profile";
Vue.use(Router);
export default new Router({
routes: [
{
path: ‘/main‘,
component: Main,
//路由嵌套
children: [
{path: ‘/user/profile‘,component: UserProfile},
{path: ‘/user/list‘,component: UserList}
]
},
{
path: ‘/login‘,
component: Login
}
]
});
路由嵌套效果图
重定向的意思大家都明白,但 Vue 中的重定向是作用在路径不同但组件相同的情况下,比如:
? 在router下面index.js的配置
{
path: ‘/main‘,
name: ‘Main‘,
component: Main
},
{
path: ‘/goHome‘,
redirect: ‘/main‘
}
路由模式有两种
hash:路径带 # 符号,如 http://localhost/#/login
history:路径不带 # 符号,如 http://localhost/login
修改路由配置,代码如下
export default new Router({
mode: ‘history‘,
routes: [
]
});
beforeRouteEnter
:在进入路由前执行
beforeRouteLeave
:在离开路由前执行
在Profile.vue中写:
export default {
name: "UserProfile",
beforeRouteEnter: (to, from, next) => {
console.log("准备进入个人信息页");
next();
},
beforeRouteLeave: (to, from, next) => {
console.log("准备离开个人信息页");
next();
}
}
参数说明:
安装 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 中进行异步请求
Profile.vue:
export default {
//第二种取值方式
// props:[‘id‘],
name: "UserProfile",
//钩子函数 过滤器
beforeRouteEnter: (to, from, next) => {
//加载数据
console.log("进入路由之前")
next(vm => {
//进入路由之前执行getData方法
vm.getData()
});
},
beforeRouteLeave: (to, from, next) => {
console.log("离开路由之前")
next();
},
//axios
methods: {
getData: function () {
this.axios({
method: ‘get‘,
url: ‘http://localhost:8080/static/mock/data.json‘
}).then(function (response) {
console.log(response)
})
}
}
}
执行
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 中进行异步请求
Profile.vue:
export default {
//第二种取值方式
// props:[‘id‘],
name: "UserProfile",
//钩子函数 过滤器
beforeRouteEnter: (to, from, next) => {
//加载数据
console.log("进入路由之前")
next(vm => {
//进入路由之前执行getData方法
vm.getData()
});
},
beforeRouteLeave: (to, from, next) => {
console.log("离开路由之前")
next();
},
//axios
methods: {
getData: function () {
this.axios({
method: ‘get‘,
url: ‘http://localhost:8080/static/mock/data.json‘
}).then(function (response) {
console.log(response)
})
}
}
}
执行
原文:https://www.cnblogs.com/xine/p/14372735.html