VUE
简介
1. vue是javaScript的渐进式框架,Vue 的核心库只关注视图层,易于上手,还便于与第三方库
(如:vue-router,vue-resource,vuex)或既有项目整合。
2. vue采用MVVM 模式,Vue.js 就是 MVVM 中的 ViewModel 层的实现者
3. jQuery频繁操作dom对象,太影响性能,使用率下降
4. vue结合了Angular的模块化开发和React的虚拟化DOM的优点
5. Axios是前端通信框架,vue只关注图形(处理DOM),不具备通信机制,因此需要整合Axios(或Jquery)
6. ElementUI: 基于VUE的UI框架(iview、ice类似)
7. WebPack: 模块打包器,主要用于打包、压缩、合并和按序加载
8. 使用HBuild打包项目为app(安卓.apk IOS .ipa)
9. NodeJS属于后台技术,Koa是框架,NPM类似于maven管理工具
安装Google浏览器vue扩展程序
1. 下载后,在Google浏览器打开扩展程序,将crx文件拖入即可
2. 第1步如果失败,将crx文件后缀改为rar,将内容压缩入文件夹中,通过加载已解压的扩展程序导入
3. F12调试即可使用vue-devtools
vue语法
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 数据显示 -->
<div>{{message}}</div>
<!-- 判断 v-else 必须挨着v-if或v-else-if -->
<div v-if="username === null">请登录</div>
<div v-else-if="username === 'zhangsan'">非法用户</div>
<div v-else>欢迎你{{username}}</div>
<!-- for循环 遍历的元素就是v-for的元素 -->
<ul>
<li v-for="user in users" v-show="user != null">{{user}}</li>
</ul>
<!-- :绑定值 -->
<a :href="url">百度</a>
<!-- 事件 @click 会调用methods里的方法 -->
<button @click="method1();">点击</button>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script></script>
<script>
var vm = new Vue({
el: "#app",
data:{
message: "Hello Vue",
username: null,
users: ["zhangsan","lisi","wangwu",this.username],
url: 'http://www.baidu.com'
},
methods:{
method1(){
alert(this.message);
}
}
});
</script>
</body>
</html>
表单绑定
1. v-model.lazy 不同时改变 只有在离开输入框后 才会调onblur和onchange事件
v-model.trim 去空格 会直接显示在开头
v-model.number 将提交的结果变为number 而不是String
2. v-show='name' 控制这个标签 如果为空 直接整句隐藏 v-if='name' 则直接不存在
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<input v-model="message"> Input内容:{{message}}
<textarea v-model="textarea"></textarea>textarea 内容:{{textarea}}
单复选框:<label for="checkbox">{{checked}}</label>
<input type="checkbox" id="checkbox" v-model="checked">
<div id="vue">
多复选框:
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<span>选中的值: {{ checkedNames }}</span>
单选按钮:
<input type="radio" id="one" value="One" v-model="picked">
<label for="one">One</label>
<input type="radio" id="two" value="Two" v-model="picked">
<label for="two">Two</label>
<span>选中的值: {{ picked }}</span>
下拉框:
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>选中的值: {{ selected }}</span>
</div>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
message: 'Hello Vue',
textarea: 'aaa',
checked: false,
checkedNames: [],
picked: '',
selected: ''
}
});
</script>
</body>
</html>
VUE组件
1. 组件是可复用的vue实例,类似于thymeleaf的th:fragment
2. 组件名作为标签,会将同样名字的值传入组件的props属性中,在组件内使用
有template模板,props参数,methods方法等,类似java属性
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<alert :msg="message"></alert>
<pay :msg="message"></pay>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script>
/* 全局模板 在所有地方都可使用 */
Vue.component('alert',{
template: '<button @click="haha">点我</button>',
props: ['msg'],
methods: {
haha(){
alert(this.msg);
}
}
});
var vm = new Vue({
el: '#app',
data: {
message: "yoo.............."
},
components: {
/* 非全局模板 */
pay: {
template: '<button @click="haha">点我</button>',
props: ['msg'],
methods: {
haha(){
alert(this.msg);
}
}
}
}
});
</script>
</body>
</html>
多组件嵌套(slot插槽)
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<top>
<top_title :title="title" slot="top_title"></top_title>
<top_content v-for="content in contents" :content="content" slot="top_content"></top_content>
</top>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script>
/* 定义一个top组件,含有俩个slot插槽(存放其他组件) */
Vue.component('top',{
template: '<div>\
<slot name="top_title"></slot>\
<ul>\
<slot name="top_content"></slot>\
</ul>\
</div>',
props: ['msg'],
});
var top_title = {
props: ['title'],
template: '<h1>{{title}}</h1>'
};
var top_content = {
props: ['content'],
template: '<li>{{content}}</li>'
}
var vm = new Vue({
el: '#app',
data: {
title: '标题',
contents: ['张三','李四','王五'],
},
components: {
top_title,
top_content,
}
});
</script>
</body>
</html>
自定义事件传递
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<top>
<top_title :title="title" slot="top_title"></top_title>
<top_content v-for="(content,i) in contents" :content="content" slot="top_content" @rmv="removeContent(i)"></top_content>
</top>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script>
/* 定义一个top组件,含有俩个slot插槽(存放其他组件) */
Vue.component('top',{
template: '<div>\
<slot name="top_title"></slot>\
<ul>\
<slot name="top_content"></slot>\
</ul>\
</div>',
props: ['msg'],
});
var top_title = {
props: ['title'],
template: '<h1>{{title}}</h1>'
};
var top_content = {
props: ['content'],
template: '<li>{{content}} <button @click="remove">删除</button></li>',
methods: {
remove(){
/* this.$emit会将相同名字的事件绑定到该方法上*/
this.$emit('rmv');
}
}
}
var vm = new Vue({
el: '#app',
data: {
title: '标题',
contents: ['张三','李四','王五'],
},
components: {
top_title,
top_content,
},
methods:{
removeContent(index){
/* 从index位置开始 删除1个元素 */
this.contents.splice(index,1);
}
}
});
</script>
</body>
</html>
计算属性computed
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<span>当前时间:{{getCurrentTime()}}</span>
<span>计算属性:{{getCurrentTime2}}</span>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script>
var vm = new Vue({
el: '#app',
methods: {
getCurrentTime(){
return Date.now();
},
},
/* 计算属性 只有在第一次进入该页面时计算 之后会直接将值返回 等效于属性 使用不需要带() */
computed: {
getCurrentTime2: function () {
return Date.now();
}
}
});
</script>
</body>
</html>
Axios通信
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<div>状态{{info.status}}</div>
<!-- 遍历对象 -->
<ul>
<li v-for="(user,i) in info.userlist">姓名:{{user.name}},下标:{{i}}</li>
</ul>
<!-- 遍历key val -->
<ul>
<li v-for="(user,i) in info.userlist"><span v-for="(val,key,i) in user" v-if="key != 'id'">key: {{key}},val: {{val}},下标{{i}}</span></li>
</ul>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script src="https://cdn.bootcss.com/axios/0.19.0/axios.min.js"></script>
<script>
var vm = new Vue({
el: '#app',
data:{
info: {}
},
/* mounted()方法会在页面加载后执行,一般用于ajax请求数据 */
mounted(){
/* 请求当前目录下的data.json */
axios.get('data.json').then(result => this.info = result.data)
}
});
</script>
</body>
</html>
data.json
{
"status": 200,
"userlist": [
{
"id": 1,
"name": "zhangsan",
"age": 23
},
{
"id": 2,
"name": "lisi",
"age": 24
}
]
}
vue-cli开发(实际开发模式)
1. 下载安装Node.js
2. 修改软件源加速器 npm install --registry=https://registry.npm.taobao.org 或使用如下语句解决 npm 速度慢的问题
npm install cnpm -g
3. 安装vue-cli npm install vue-cli -g (vue list可以查看模板)
4. 进入工作目录基于webpack模板的vue工程 vue init webpack 工程名
5. cd 工程名 npm install 安装依赖
6. npm run dev 运行
目录结构
1. build 和 config:WebPack 配置文件,帮助打包
2. node_modules:用于存放 npm install 安装的依赖文件
3. src: 项目源码目录
4. static:静态资源文件
5. .babelrc:Babel 配置文件,主要作用是将 ES6 转换为 ES5
6. index.html:首页,仅作为模板页,实际开发时不使用
7. package.json:项目的配置文件
name:项目名称
version:项目版本
description:项目描述
author:项目作者
scripts:封装常用命令
dependencies:生产环境依赖
devDependencies:开发环境依赖
webpack.config.js 配置文件(打包)
entry:入口文件,指定 WebPack 用哪个文件作为项目的入口
output:输出,指定 WebPack 把处理完成的文件放置到指定路径
module:模块,用于处理各种类型的文件
plugins:插件,如:热更新、代码重用等
resolve:设置路径指向
watch:监听,用于设置文件改动后直接打包
vue-router 路由
1. 一般用Vue做的都是单页应用(index.html),a标签不起作用,页面跳转需要
vue-router 路由(实际就是组件切换);
2. 安装vue-router npm install vue-router --save-dev(开发环境使用)
3. src/router/index.js为核心,配置路由
4. main.js增加route配置
5. 增加路由显示router-view和跳转router-link
index.js
/* 引入 Vue */
import Vue from 'vue'
/* 引入 路由 */
import Router from 'vue-router'
/* 引入组件 */
import Content from '../components/Content'
/* 使用 */
Vue.use(Router);
// 配置路由
export default new Router({
// 去掉#
mode: 'history',
routes: [
{
// 路由路径
path: '/content',
// 路由名称
name: 'Content',
// 跳转到组件
component: Content
}
]
}
)
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'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
});
App.vue
<template>
<div id="app">
<img src="./assets/logo.png">
<router-link to="/">首页</router-link>
<router-link to="/content">内容</router-link>
<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>
嵌套路由和参数传递
import Vue from 'vue'
import Router from 'vue-router'
import Login from '../views/Login'
import Main from '../views/Main'
import UserProfile from '../views/user/UserProfile'
import UserList from '../views/user/UserList'
Vue.use(Router);
export default new Router({
// 去掉#
mode: 'history',
routes: [
// 登录页
{
path: '/login',
name: 'Login',
component: Login
},
// 首页
{
path: '/main',
name: 'Main',
component: Main,
children:[
{
//在组件中使用{{$route.params.id}}接收
path: '/user/profile/:id',
name: 'UserProfile',
component: UserProfile
},
{
path: '/user/list',
name: 'UserList',
component: UserList
}
]
}
]
})
路由钩子与异步请求
1. beforeRouteEnter:在进入路由前执行
beforeRouteLeave:在离开路由前执行
export default {
props: ['id'],
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 是组件实例
1. vue-cli使用异步请求要先安装axios
npm install axios -s
2. 在 main.js中添加依赖和设置
import axios from 'axios';
Vue.prototype.axios = axios;
3. 请求
<template>
<div>
用户个人信息 id={{$route.params.id}}
</div>
</template>
<script>
export default {
name: "UserProfile",
beforeRouteEnter: (to,from,next) =>{
next(vm => {
vm.getData();
});
},
methods: {
getData(){
this.axios({
method: 'get',
url: 'http://18.179.44.31:8080/simpleStatements/homepage/list.do'
}).then(response =>{
console.log(response);
}).catch(error =>{
console.log(error);
})
}
}
}
</script>
<style scoped>
</style>
ElementUI
1. ElementUI是vue的一个组件库,能够快速搭建项目,类似于bootstrap
2. 安装 npm i element-ui -S
3. 安装 SASS 加载器 npm install sass-loader node-sass
4. npm install
使用
1. 在main.js中添加依赖,并使用
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
Vuex
1. 状态管理模式,采用集中式存储管理应用的所有组件的状态(Cookie)
2. 安装vuex npm install vuex --save
3. main.js添加依赖
import Vuex from 'vuex'
Vue.use(Vuex);
4. 登录出增加 sessionStorage.setItem('isLogin', 'true'); 记录登录成功
5. main.js添加路由钩子(等效拦截器)router.beforeEach((to, form, next)
router.beforeEach((to, from, next) => {
let isLogin = sessionStorage.getItem("isLogin");
// 注销
if (to.path == '/logout') {
// 清空
sessionStorage.clear();
next('/login');
} else if (to.path == '/login') {
if (isLogin != null) {
next('/main');
}
} else if (isLogin == null && to.path != '/login') {
next('/login');
}
next();
});
模块化存储
1. 在src/store/modules下建立user.js
const user = {
state: sessionStorage.getItem('userState') ? JSON.parse(sessionStorage.getItem('userState')) : {
user: {
username: ''
}
},
getters: {
getUser(state) {
return state.user;
}
},
mutations: {
setUser(state, user) {
state.user = user;
}
},
actions: {
asyncSetUser(context, user) {
context.commit('setUser', user);
}
}
};
export default user;
2. src/store 下的index.js引入
import Vue from 'vue'
import Vuex from 'vuex'
import user from './modules/user'
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
user
}
});
3. App.vue增加页面刷新,将store数据存储到sessionStorage
<script>
export default {
name: 'App',
mounted() {
window.addEventListener('unload', this.saveState);
},
methods: {
saveState() {
// 模块化后,调用 state 的代码修改为 this.$store.state.user
sessionStorage.setItem('userState', JSON.stringify(this.$store.state.user));
}
}
}
</script>