第一章-Vue概述
官方文档:https://cn.vuejs.org/v2/guide/
为什么学习Vue?在以往的ssm+jsp已经可以满足需求,我们已经可以用Bootsrap去写一个好看的页面了,为什么还需要学习Vue呢?Jsp页面的弊端,我们显示一个Jsp页面,需要包含html+css+图片,这些静态资源和数据动态资源,静态资源请求比较快,而且一般不会变化,却要等待动态数据一起返回响应,这势必会增加服务器的压力,那么有没有这样一种可能,我把静态页面和动态查询数据分开,静态数据利用缓存保存起来,动态数据利用Ajax等异步请求数据。
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式JavaScript框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,方便与第三方库或既有项目整合。
学习vue我们必须之到它的7个属性,8个 方法,以及7个指令。787原则
-
el属性
-
- 用来指示vue编译器从什么地方开始解析 vue的语法,可以说是一个占位符。
-
data属性
-
- 用来组织从view中抽象出来的属性,可以说将视图的数据抽象出来存放在data中。
-
template属性
-
-
methods属性
-
- 放置页面中的业务逻辑,js方法一般都放置在methods中
-
render属性
-
-
computed属性
-
-
watch属性
-
- watch:function(new,old){}
- 监听data中数据的变化
- 两个参数,一个返回新值,一个返回旧值,
1Vue介绍
什么是MVVM?
- 概念介绍
- MVVM分为三个部分:分别是M(Model,模型层 ),V(View,视图层),VM(ViewModel,V与M连接的桥梁,也可以看作为控制器)
1、 M:模型层,主要负责业务数据相关,javaScript对象;
2、 V:视图层,负责视图相关,细分下来就是html+css层(DOM,HTML操作的元素);
3、 VM:V与M沟通的桥梁,负责监听M或者V的修改,是实现MVVM双向绑定的要点;vue.js就是VM层的实现
- MVVM支持双向绑定,意思就是当M层数据进行修改时,VM层会监测到变化,并且通知V层进行相应的修改,反之修改V层则会通知M层数据进行修改,以此也实现了视图与模型层的相互解耦;

2入门案例
CND网上版本:https://cdn.staticfile.org/vue/2.2.2/vue.min.js
官网下载地址:https://cn.vuejs.org/v2/guide/installation.html
**注意:**Vue.js 不支持 IE8 及其以下 IE 版本。
1使用IDEA进行开发Vue,需要plugins下载Vue
2下载完毕后,右击项目,新建Vue Compoent,若没有这个Vue组件,去settings下的Editor,选择File and Code Templates手动新建一个template。
3新建一个html,第一个vue程序。
{{差值表达式,只能用在两个标签间,不能用在标签内部}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
</head>
<body>
<div id="app">
<p>{{ message }}</p>
<p>asddddd</p>
</div>
<script>
new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
}
})
</script>
</body>
</html>
|
流程控制
v-if / v-else-if / v-else (若符合条件就渲染,不符合不会渲染)
此外还可以使用v-show(区别是show是display,若是反复切换的内容使用v-show,因为其只渲染一次。)
v-for 指令需要以 site in sites 形式的特殊语法, sites 是源数据数组并且 site 是数组元素迭代的别名。site,key in sites ,{{key}}为索引0开始,若数据结构为数组key是索引,也可以是任意单词,若数据结构为对象key是键。
== 用于比较两者是否相等,忽略数据类型。
=== 用于更严谨的比较,值和值的数据类型都需要同时比较。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
<!DOCTYPE html>
<html xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<script src="vue/vue.js"></script>
</head>
<body>
<div id="div2">
<h1 v-if="m1=='B'">B</h1>
<h1 v-else-if="m1=='A'">A</h1>
<h1 v-else>CD</h1>
<ol>
<li v-for="item in site">
{{item.name}}
</li>
</ol>
</div>
<script>
var vm1=new Vue({
el:'#div2',
data: {
m1: "B",
message: "hello world",
}
});
var vm1=new Vue({
el:'#div2',
data: {
m1: "B",
message: "hello world",
site: [
{name:"卢森林"},
{name:"卢森林1"},
{name:"卢森林2"},
]
}
});
</script>
</body>
</html>
|
site in sites 循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<ol>
<li v-for="a1,key,index in arr[0]">
下标:{{index}} 键:{{key}} 值:{{a1}}
下标:0 键:f1 值:micro1
下标:1 键:f2 值:micro2
下标:2 键:f3 值:micro3
</li>
</ol>
<hr />
<h6 v-for="ls,key in list">
{{key}}--{{ls}}--{{index}}
0--july1--数据格式为数组,没有index
1--july2--
2--july3--
</h6>
<script>
let app=new Vue({
el:"#oaDiv",
data:{
arr:[{f1:"micro1",f2:"micro2",f3:"micro3"},"a2","a3"],
list:["july1","july2","july3"]
}
</script>
|
当需要在循环中使用if判断时,可以使用计算属性进行替代。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
<!-- if和for不能同时使用,用computed代替" -->
<div id="ifdiv">
<ol>
<li v-for="d,key,index in evenAge" >
<p>{{index}}-----</p>
<p>{{key}}------{{d.name}}----{{d.age}}----</p>
</li>
</ol>
</div>
<script>
let ifapp=new Vue({
el:"#ifdiv",
data:{
lists:[
{name:"张三1",age:16,sex:"F"},
{name:"张三2",age:17,sex:"F"},
{name:"张三3",age:18,sex:"F"}
]
},
computed:{
evenAge:function(){
return this.lists.filter(function(list){
if(list.age%3==0){
return list;
}
})
}
}
});
</script>
|
事件v-on
sayHi:function(event){event.target.value== 当前事件的对象的value值}
methods中方法的this指的是当前的vue对象,若使用vue中data要加上this。
v-on:input="id"可以简写为@input="id”
事件还有一些修饰符on.stop(阻止事件传播)、submit.prevent、等
加上window.load=function(){代码}保证在dom加载完成后才能操作代码
若有jquery,也可以用$(function(){代码})
事件可以直接写在行内代码中,也可以给Vue()加一个methods:{}写在这个里面。
想要直接调用这个方法的话,可以vm.sayHi();
关于v-on:click[DOM事件类型]=“sayHi”,DOM事件类型有很多。
v-on:keyup.end="add"事件修饰符,click.once只能点一次
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="vue/vue.js"></script>
<script>
window.onload=function () {
//click事件绑定
var vm=new Vue({
el: "#hello",
data: {
name:'赵明明',
age: 1
}
});
//关于methods方法
var app=new Vue({
el: "#app",
data: {
name: "欧阳克"
},
methods: {
sayHi: function () {
alert(this.name);
}
}
});
}
</script>
</head>
<body>
<!-- v-on:click在行内写方法 -->
<div id="hello" v-on:click="age += 1">你好{{ name + age }}</div>
<!-- v-on:click绑定methods,点击后会出现Name的值-->
<div id="app" v-on:click="sayHi">
<p>小app</p>
</div>
</body>
</html>
|
双向绑定bothwayBind
==1<v-model>==
==2<v-bind>==
3自定义指令
4:class
你可以用v- model指令在表单<input> 、<textarea> 及<select> 元素上创建双向数据绑定。
它会根据控件类型自动选取正确的方法来更新元素。尽管有些神奇,但v-model本质上不过是语法糖。它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
注意: v-model会忽略所有表单元素的value. checked、 selected 特性的初始值而总是将Vue实例的数据作为数据来源。你应该通过JavaScript在组件的data选项中声明初始值!
若是select,model绑定的值会匹配select下option的value,若相同则默认选中。若没有则为空。(ios用户会出现第一个选项无法选择,因此可以设置,一个”==请选择=="的选项,并且设为disabled)
v-model.修饰符 。可以有一些修饰符:lazy离开框才显示、number吧值转为number若其为NaN则为原值、trim去除首尾部空格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
<!DOCTYPE html>
<html xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<script src="vue/vue.js"></script>
</head>
<body>
<div id="div1">
输入的文本:<input type="text" v-model="message">
{{message}}
<br>
性别<input type="radio" value="男" v-model="sex">男
性别<input type="radio" value="女" v-model="sex">女
<br>
你选中了:{{sex}}
<br>
<select v-model="select">
<option value="1" disabled>==请选择==</option>
<option value="广东">广东</option>
<option>湖北</option>
<option>河南</option>
</select>
</div>
<script>
var vm=new Vue({
el:'#div1',
data: {
message: "你好啊",
sex: "",
select: ""
}
});
</script>
</body>
</html>
|
==v-bind==缩写为“ : ”
:v-bind用于绑定属性和数据 ,其缩写为“ : ” 也就是v-bind:id 等同 :id
:v-model用在表单控件上的,用于实现双向数据绑定,所以如果你用在除了表单控件以外的标签是没有任何效果的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<!DOCTYPE html>
<html xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<script src="vue/vue.js"></script>
</head>
<body>
<div id="div1">
<span v-bind:title="message">
鼠标悬停查看此处动态绑定的提示
</span>
</div>
<script>
var vm=new Vue({
el:'#div1',
data: {
message: "hello world"
}
});
</script>
</body>
</html>
|
v-once指令:元素的数据只出现一次,数据修改不影响此元素。
v-html指令:好比InnerHTML,直接把title当作html标签解析
v-text指令:把值当作纯文本输出。
1
2
|
<p v-once>{{title}}</p>
<p v-html>{{title}}</p>
|
3自定义指令
更多指令:https://cn.vuejs.org/v2/guide/custom-directive.html#ad
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
<!DOCTYPE html>
<html xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<script src="vue.js"></script>
</head>
<body>
<div id="d1">
<input type="text" v-focus="1==2" />
</div>
<hr />
<script>
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
el.value='ddsa' //改变原对象的值
// 聚焦元素
el.focus()
}
})
let d11=new Vue({
el:"#d1",
data:{
message:"hello word!"
}
});
</script>
</body>
</html>
|
4:class
1
2
3
4
5
6
7
8
9
10
11
12
13
|
:class中应该放置的是{a1:class1,a2:class2}的对象
vue会根据{}中的true和false控制是否显示。
也可以不要{}直接放置hehe。就会解析为hehe对象。也可以直接使用数组
<div class="h1" :class="{hehe:false}">
---此时不会有hehe,若为true,也仅仅为hehe而不是字符串a1、a2
</div>
<script>
data:{
message:"hello word!",
flag:true,
hehe:{a1:true,a2:true}
}
</script>
|
Vue组件
emp.vue组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
<template>
<div>
<p>hello my name is Emp.vue!!!</p>
<p>员工页面</p>
<p>传值Name:<input type="text" v-model="name" ></p>
<p>emp.vue的name:{{name}}</p>
<p>main.js的name: {{this.$store.getters.getName}}</p>
</div>
</template>
<script>
export default{
name:"emp",
data(){
return{
name:'初始值'
}
},
watch:{
name(val){
this.$store.dispatch('changeName',val)
}
}
}
</script>
<style scoped="scoped">
</style>
|
组件就是可以重复利用的Vue实例,就像是模版。
和vue实例区别是,自定义组件要有一个root ele,父子组件data无法共享,组件可有data,methods,computed,但是data必须是个函数。
数据父传子:若在父组件使用时,参数不加v-bind:yoyo那就是字符串,若加:则是父组件的对象。
1
2
3
4
5
6
7
8
9
|
<myli组件名称 yoyo="123字符串"></myli组件名称>
<script>
Vue.component("myli组件名称",{
// props: ['yoyo接受参数'] ,
props:{yoyo:String,calendar: String,signal:Boolean},
template: '<li>{{ yoyo 使用参数}}</li>'
});
</script>
|
prpos可以是数组也可以是对象,是对象时可以限制类型,Number,String,Boolean,Array,Object,Function,null(不限制类型)
数据子传父:
1调用子组件时@myevent="handleEvent”
然后在父组件定义handleEvent方法,在子组件中的某方法里去触发这个方法this.$emit("myevent","hello word","ooo");
后面两个是参数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
<!DOCTYPE html>
<html xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<script src="vue.js"></script>
</head>
<body>
<div id="d1" >
<!-- <button v-on:click="isShow=!isShow">点击</button> -->
<navbar @myevent="handleEvent"></navbar>
<sidebar v-show="isShow"></sidebar>
</div>
<hr />
<script>
Vue.component("navbar",{
template:"<button v-on:click='handleClick'>点击</button>",
methods:{
handleClick(){
this.$emit("myevent","hello word","ooo");
}
}
});
Vue.component("sidebar",{
template:'<div><ul><li>1111</li><li>2222</li><li>3333</li></ul></div>',
});
let app=new Vue({
el:'#d1',
data:{
isShow:false
},
methods:{
handleEvent(mes,me){
console.log(mes+" "+me);
this.isShow=!this.isShow
}
}
});
</script>
</body>
</html>
|
组件应用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
<!DOCTYPE html>
<html xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<script src="vue/vue.js"></script>
</head>
<body>
<div id="div1">
<li>hell1o</li>
<myli v-for="item in information" v-bind:yoyo="item"></myli>
</div>
<script>
Vue.component("myli",{
props: ['yoyo'] ,
template: '<li>{{ yoyo }}{{name}}{{age}}</li>',
data(){
return {
name: "lusenlin",
age:15
}
}
});
var vm=new Vue({
el: '#div1',
data: {
information: ['湖北','hulan','guangdong']
}
});
</script>
</body>
</html>
|
全局变量
混入mixin
//混入就是抽取出来东西(方法、data等)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
<!DOCTYPE html>
<html xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<script src="vue.js"></script>
<script src="vue-router.js"></script>
</head>
<body>
<div id="d1">
<p>num:{{num}}</p>
<p><button @click="minus">-</button></p>
<p><button @click="add">+</button></p>
</div>
<hr />
<script>
//Vue.mixin({})为全局混入。会对所有的生效
var addLog={
data:{
a1:10,
a2:20
}
,
created:function(){
//只会出现在调用时创建调用一次
console.log("--created--"+this.num)
}
,
updated:function(){
//数据出现修改就会调用
console.log("数据发生了变化--"+this.num)
},
methods:{
minus:function(){
this.num--;
}
}
}
let d11=new Vue({
el:"#d1",
data:{
message:"hello word!",
num:0
},
methods:{
add:function(){
console.log("mixin中的data:"+this.a1);
this.num++
}
},
mixins:[addLog]
});
</script>
</body>
</html>
|
Axios
Axios是一个开源的可以用在浏览器端和NodeJS 的异步通信框架,它的主要作用就是实现AJAX
异步通信。
Vue.js 2.0 版本推荐使用 axios 来完成 ajax 请求。
Axios 是一个基于 Promise 的 HTTP 库,可以用在浏览器和 node.js 中。
使用的 mounted() {}方法是在html页面加载后执行的,还有一个create()方法
需要导入包若是vue-cli工程利用npm install axios安装
1
|
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
|
为方便起见,为所有支持的请求方法提供了别名
axios.request(config)
axios.get(url[, config])
axios.delete(url[, config])
axios.head(url[, config])
axios.post(url[, data[, config]])
axios.put(url[, data[, config]])
axios.patch(url[, data[, config]])
axios. get(地址?key=value&key2=value2).then(function(response){},function(err){})
axios post(地址,参数对象).then(function(response){},function(err){})
若支持EX6回调函数可以写为.then(response => {一行代码可以不用;也不用中括号。这里使用this.info可以直接获得和改变Vue对象data的值。})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
<!DOCTYPE html>
<html xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<script src="vue/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="div1">
{{info}}
</div>
<script>
var vm=new Vue({
el:'#div1',
data(){
return {
info:"hello my name is tom"
}
},
mounted() {
axios.get("https://autumnfish.cn/api/joke/list?num=4").then(response =>
{
console.log(response.data.jokes[2]);
console.log(this.info);
this.info=response.data.jokes[3];
}
)
}
});
</script>
</body>
</html>
|
Vue-cil中的Axios
vue-axios和axios区别https://www.baidu.com/link?url=2TEQtDUeXQzw6ovqBVIoM1SfTV4yy3dtN2DyRCGv4HDJEl3ooRSO5JsqNhF0AMUA&wd=&eqid=87d035b900087cc8000000045efef835
安装Axios 命令npm install axios
1
2
3
4
5
6
7
|
//main.js导入axios
//导入axios
import axios from 'axios'
import VueAxios from 'vue-axios'
//使用路由和 Ui
Vue.use(VueAxios,axios);
|
2另一种方式
1
2
3
4
5
6
7
8
9
10
11
12
|
//2.src/main.js中配置axios
import axios from 'axios'
Vue.prototype.$axios = axios
//3.组件中使用axios
this.$axios.get("dept/listparent").then(function(){
}).catch(function(error){
console.log(error);
})
//挂载Vue.prototype.$http=axios
//设置访问根路径
axios.defaults.baseURL="http://localhost:9000"
|
进行使用,一般来说,进入一些页面会通过Id获取信息,比如props是接收传递来的信息,然后data(){return {k:v}}用来显示信息,通过钩子函数可以发送aixos请求。
params是添加到url的请求字符串中的,用于get请求。
而data是添加到请求体(body)中的, 用于post请求。
2、post请求:==添加使用的是aixos方法2,用qs处理,或者SpringBoot参数加@RequestBody==表单参数是在请求体中,也是name=value&name1=value1的形式在请求体中。
POST表单请求提交时,使用的Content-Type是application/x-www-form-urlencoded,而使用原生AJAX的POST请求如果不指定请求头RequestHeader,默认使用的Content-Type是text/plain;charset=UTF-8。
在html中form的Content-type默认值:Content-type:application/x-www-form-urlencoded:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
<script>
//post请求传递两个参数
this.$axios.post("/qxRole/addMemberForRole",
{roleId:this.roleId,emps:this.transferValue})
.then(response =>{
if(response.data.code==200){
this.$message({
message:'添加成功',type:'success'
})
this.getRoles()
}else{
this.$message({
message:'添加失败',type:'error'
})
}
this.memberDialogVisible=false
})
</script>
//SpringBoot接收时需要处理
//为角色添加成员
@RequestMapping("/addMemberForRole")
public ResultObj addMemberForRole(@RequestBody Map<String, Object> map){
// System.out.println("roleId:"+map.get("roleId")+" emps:"+map.get("emps"));
//先删除,再添加
roleService.addMemberForRole((Integer) map.get("roleId"), (List) map.get("emps"));
return ResultObj.getSuccess(null);
}
|
Vue-cli中跨域问题
1
2
3
4
5
6
7
8
|
//config下的index.js
proxyTable: {
"/dept/*":{
target: 'http://localhost:8081', //源地址
changeOrigin: true //改变源
}
}
|
计算属性等
调用方法时,每次都需要进行计算,既然有计算过程则必定产生系统开销,那如果这个结果是不经常变化的呢?此时就可以考虑将这个结果缓存起来,采用计算属性可以很方便的做到这一点, 算属性的主要特性就是为了将不经常变化的计算结果进行缓存,以节约我们的系统开销;
vue中change方法是没有作用的
1computed是一个属性,可以直接调用。会把结果缓存到内存,除非数据改变,否则不会重新计算。
2method是一个方法,需要加括号。每次都会执行。
3watch监听属性,响应数据变化
4filters过滤属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
<!DOCTYPE html>
<html xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<script src="vue/vue.js"></script>
</head>
<body>
<!--计算属性-->
<div id="div1">
{{sayHi1}}
<br>
{{sayHi()}}
</div>
<script>
var vm=new Vue({
el:'#div1',
data: {
message: "hello ,January,February,March"
},
methods: {
sayHi: function(){
return "hello my method name is sayHi"+new Date();
}
},
computed: {
sayHi1: function () {
this.message;
return "hello my method name is sayHi1"+new Date();
}
}
});
</script>
</body>
</html>
|
3watch所监听的是属性,==属性监听==
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
<!DOCTYPE html>
<html xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<script src="vue.js"></script>
</head>
<body>
<div id="d1">
千克<input type="text" v-model="kilogram" /><br />
等于<br />
克<input type="text" v-model="gram" />
</div>
<hr />
<script>
let d11=new Vue({
el:"#d1",
data:{
gram:'',
kilogram:''
},
watch:{
kilogram:function(val){
console.log("kilogram:"+val);
this.kilogram=val;
this.gram=this.kilogram*1000;
},
gram:function(val){
console.log("gram:"+val);
this.gram=val;
this.kilogram=this.gram/1000;
}
}
});
</script>
</body>
</html>
|
4filters过滤属性
详情:https://cn.vuejs.org/v2/guide/filters.html
1
2
3
4
5
6
7
8
9
10
|
克:{{kilogram | toGram}}
filters:{
toGram:function(v){
if(isNaN(v)==false{
return "*"+parseFloat(v).toFixed(2);
};
return '';
}
}
|
插槽slot
key的作用就是为了防止更新了数据的时候重新渲染整个列表,有key相当于做了一个缓存,只会去重新渲染更新了的数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
<!DOCTYPE html>
<html xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<script src="vue/vue.js"></script>
</head>
<body>
<div>
<p>湖北</p>
<ul>
<li>襄阳</li>
<li>武汉</li>
<li>宜昌</li>
</ul>
</div>
<br><hr color="red">
<div id="div1">
<text1>
<province slot="province" v-bind:p1="pp"></province>
<city slot="city" v-bind:c1="c1" v-for="(c1,index) in citys" v-bind:key="index"></city>
</text1>
</div>
<br><hr color="red">
<script>
Vue.component("text1",{
template: '<div>\
<slot name="province"></slot>\
<ul>\
<slot name="city"></slot>\
</ul>\
</div>'
});
Vue.component("province",{
props: ['p1'],
template: '<p>{{p1}}</p>'
});
Vue.component("city",{
props: ['c1'],
template: '<li>{{c1}}</li>'
});
var vm=new Vue({
el:'#div1',
data: {
pp: '河南',
citys: ['信阳','南阳','郑州']
}
});
</script>
</body>
</html>
|
数组方法
增删改
方法向/从数组中添加/删除项目,然后返回被删除的项目。
arrayObject.splice(index,howmany,item1,…..,itemX)。
- index 必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
- howmany 必需。要删除的项目数量。如果设置为 0,则不会删除项目。
- item1 可选,向数组添加的新项目。
复制
Array(2).fill(item)把tiem进行复制后返回
1
2
3
4
5
6
7
|
var empFromDept=[]
for (let i = 0; i < rep.data.data.length; i++) {
empFromDept.push({
key: rep.data.data[i].oid,
label: rep.data.data[i].empName
});
}
|
向数组中添加this.transferValue.push(rep.data.data[i].oid)
购物车案例
vue操作数组:https://www.cnblogs.com/Zhengxiaoxiao/p/10823150.html
==可以利用Vue.set简化,事件中传递对象,操作对象也可成功==
数字保留两位小数:parseFloat(money).toFixed(2);
判断数组中是否有元素:arr.indexOf(ele) 若返-1则不存在
this.arr.splice(下标1,参数2);
三种用法 替换、插入未验证
1删除 下标(从第几个开始删),参数2删除几个
2替换 下标(从第几个开始),替换几个,后面跟着替换的元素
3插入 下标(从第几个开始),0,插入的元素。[1,2,3] arr.splice(1,0,3) [1,3,2,3]
对数组进行循环this.shoppingTrolly.forEach((v,k)=> { });
对数组进行删除Vue.delete(this.shoppingTrolly,ind);
对数组进行添加this.single.push(v.commodityName);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
<!DOCTYPE html>
<html xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<script src="vue.js"></script>
</head>
<body>
<!-- 购物车 一个集合对象,包含多个 {商品名称,价格,图片}
全选,全不选,删除
总价/总数量
-->
<div id="commoditysDiv">
<table>
<tr>
<th><input type="checkbox" v-on:click="seleteAllCommodity"
/> 全选
{{single.length===shoppingTrolly.length}}
</th>
<th>商品名称</th>
<th>价格</th>
<th>图片</th>
<th>数量</th>
<th>操作</th>
</tr>
<tr>
<td colspan="6"></td>
</tr>
<tr v-for="commodity,key in shoppingTrolly">
<td><input type="checkbox" v-on:click="singleSelete(key,commodity.commodityName)"
:checked="single.indexOf(commodity.commodityName)>=0" /> </td>
<td>{{commodity.commodityName}}</td>
<td>{{commodity.commodityPrice}}</td>
<td>
<img :src="commodity.commodityPicture"
width="80px" height="80px">
</td>
<td>
<button v-on:click="minus(key)">-</button>
<input type="text" v-model="commodity.amount">
<button v-on:click="add(key)">+</button>
</td>
<td><button v-on:click="delete1(key)">删除</button></td>
</tr>
</table>
<br/>
总数量:{{computeAmount}}
<br/>
总价格:{{computePrice}}
</div>
<hr />
<script>
let d11=new Vue({
el:"#commoditysDiv",
data:{
shoppingTrolly:[
{commodityName:"雪碧",commodityPrice:3.9,commodityPicture:"img/coke.jpg",amount:1},
{commodityName:"橘子",commodityPrice:6.9,commodityPicture:"img/fatOrange.jpg",amount:1},
{commodityName:"猪蹄子",commodityPrice:29.9,commodityPicture:"img/pig.jpg",amount:1},
{commodityName:"milk",commodityPrice:2.1,commodityPicture:"img/fds.jpg",amount:1},
],
seleteAll:false,
single:[],
},
methods:{
add:function(ind){
//数量加
console.log("++++"+ind);
this.shoppingTrolly[ind].amount++
},
minus:function(ind){
//数量减
console.log("-----"+ind);
this.shoppingTrolly[ind].amount--
},
delete1:function(ind){
//数组中删除 返回值是0
开始的
var index = this.single.indexOf(this.shoppingTrolly[ind].commodityName);
alert(index+" "+this.single.length);
this.single.splice(index,1);
//删除商品
console.log("删除"+ind);
Vue.delete(this.shoppingTrolly,ind);
},
seleteAllCommodity:function(){
//全选商品
//event.currentTarget.checked表示点击完后该选择框的状态
console.log("全选商品"+this.seleteAll);
console.log("数组:"+this.single);
if(event.currentTarget.checked){
this.single=[];
//全选
this.shoppingTrolly.forEach((v, k) => {
//第一个是值,第二个是key
this.single.push(v.commodityName);
});
}else{
//全不选
this.single=[];
}
},
singleSelete:function(ind,name){
//单选商品
console.log("下标:"+ind+" 名称"+name);
if(event.currentTarget.checked){
//选
this.single.push(name);
}else{
//不选 进行删除
//Vue.delete(this.single,name);
for (var i = 0; i < this.single.length; i++) {
if (this.shoppingTrolly[ind].commodityName === this.single[i]) {
//第一个参数是从第几个元素开始删除, 第2个参数是删除多少个
this.single.splice(i, 1);
this.selectAll = false;
break;
}
}
}
}
},
computed:{
computeAmount:function(){
let amount=0;
this.shoppingTrolly.forEach((v,k)=> {
//第一个是值,第二个是key
if(this.single.indexOf(v.commodityName)>=0){
amount=amount+v.amount;
}
});
return amount;
},
computePrice:function(){
let money=0;
this.shoppingTrolly.forEach((v,k)=> {
//第一个是值,第二个是key
if(this.single.indexOf(v.commodityName)>=0){
money=money+v.commodityPrice*v.amount;
}
});
return parseFloat(money).toFixed(2);
}
}
});
</script>
</body>
</html>
|
Router路由
简单案例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
<!DOCTYPE html>
<html xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<script src="vue.js"></script>
<script src="vue-router.js"></script>
</head>
<body>
<div id="d1">
<router-link to="/component1">component1</router-link>
<router-link to="/component2">component2</router-link>
<router-link to="/component3">component3</router-link>
<hr />
<router-view></router-view>
</div>
<hr />
<script>
//1定义组件 可以从其它文件import进来
//const和let、var类似,其含义为不可变的必须初始化的
const component1={
template:'<div>hello word!1111111</div>'
}
const component2={
template:'<div>hello word!22222222</div>'
}
const component3={
template:'<div>hello word!3333333</div>'
}
//2定义路由
const routes=[
{path:'/component1',
component:component1
},
{path:'/component2',
component:component2
},
{path:'/component3',
component:component3
},
]
//3创建路由实例
const router=new VueRouter({
routes:routes //可以只缩写为routes,其实就是引用数组
})
let d11=new Vue({
el:"#d1",
data:{
message:"hello word!"
},
router:router
});
</script>
</body>
</html>
|
第二章-Vue-cli
1Vue-cli
vue-cli官方提供的一个脚手架,用于快速生成一个vue的项目模板;
预先定义好的目录结构及基础代码,就好比咱们在创建Maven项目时可以选择创建- - 个骨架项目,这个骨架项目就是脚手架,我们的开发更加的快速;
主要功能:
●统一的目录结构
●本地调试
●热部署
●单元测试
●集成打包上线
vue ui图形化的创建项目的工具
1node.js含npm
安装nodejs Node.js官网直接下载。(node -v或者npm -v出现版本号就可以,包含npm)
Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型。
npm,就是一个软件包管理工具,就和linux下的apt软件安装差不多!(类似maven)
安装Node.js淘宝镜像加速器(cnpm)
npm install cnpm -g ( g就是全局安装)安装过程可能有点慢~ ,耐心等待!虽然安装了cnpm,但是尽量少用!
安装的位置: C: \Users \Administrator \AppData\Roaming\npm
** 2npm**
npm -v 查看npm是版本
Npm命令解释
npm install moduleName 安装到项目目录下
npm install -g moduleName 安装到全局,具体看npm config prefix的位置
npm install -save moduleName : –save 的意思是将模块安装到项目目录下,并在
package文件的dependencies节点写入依赖(自动写入打包目录),-S为该命令的缩写
npm install -save-dev moduleNam e: –save-dev的意思是将模块安装到项目目录下,并
在package文件的devDependencies节点写入依赖,-D 为该命令的缩写
常用命令
功能 |
命令 |
安装axios |
npm install axios -s |
安装vue-axios |
|
|
|
|
|
|
|
|
|
3安装vue-cli
下载最新版本
==cnpm install -g @vue/cli== 最新版本使用https://cli.vuejs.org/zh/guide/prototyping.html
cnpm install vue-cli -g 之前版本使用
#下完后,查看可以基于哪些模板创建vue应用程序,通常我们选择webpack
vue list查看模版无法使用,以下是2.x版本。
创建vue-cli项目 (==vue ui也可以做到==)
1然后cmd找到一个文件夹,执行vue init webpack my[项目名]vue。
2出现Runtime+Complier运行加编译,Runtime-only仅运行,选择第一个。
3 然后project name选择3个回车就好,选择4个no,然后询问是否xxx,选择自己创建。
说明:
●Project name:项目名称,默认回车即可
●Project description: 项目描述,默认回车即可
●Author: 项目作者,默认回车即可
●Install vue-router:是否安装vue-router,选择n不安装(后期需要再手动添加)
●Use ESLint to lint your code:是否使用ESLint做代码检查,选择n不安装(后期需要再手
动添加)
●Set up unit tests: 单元测试相关,选择n不安装(后期需要再手动添加)
●Setup e2e tests with Nightwatch:单元测试相关,选择n不安装(后期需要再手动添加)
●Should we run npm install for you after the project has been created: 创建完成后直
接初始化,选择n,我们手动执行;运行结果!,当前目录出现了文件夹。
初始化并运行:1切换当前目录cd myvue,2npm install 安装(cnpm install安装更快),3npm run dev(启动当前项目)
启动后出现运行地址,打开出现vue界面,说明项目创建Ok
停止命令是,Ctrl+C停止这个项目
可以用IDEA打开它,查看结构。
创建错误
1vue-cli Failed to dowboad xxx:self signed xx
在C:\Users\Administrator\AppData\Roaming\npm\node_modules\vue-cli\node_modules\download\index.js把//rejectUnauthorized: process.env.npm_config_strict_ssl !== ‘false’改为rejectUnauthorized: false
vue ui创建新项目
直接启动vue ui然后根据ui界面进行创建
2Vue-cli结构
1 package.json是相当于pom.xml的文件,这里面存放了依赖
2 config文件存放的配置,比如index.js可设端口号等
3 node_modules存放的下载的依赖,比如router.js、Vue的依赖等
4 src下是自己写的代码
1package.json详解
devDependencies
用于开发环境,生产环境不会被打包。
dependencies
用户发布环境
devDependencies是只会在开发环境下依赖的模块,生产环境不会被打入包内。通过NODE_ENV=developement或NODE_ENV=production指定开发还是生产环境。
而dependencies依赖的包不仅开发环境能使用,生产环境也能使用。其实这句话是重点,按照这个观念很容易决定安装模块时是使用–save还是–save-dev。
cli3中scripts命令
npm run serve时会把process.env.NODE_ENV设置为‘development’;
npm run build 时会把process.env.NODE_ENV设置为‘production’
N Webpack
WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。
之前我们使用javaScript时候,是一个一个script文件导入的,这种加载方式有弊端:全局作用域容易造成变量冲突,文件只能按照顺序加载,要主观解决模块和代码库的依赖关系,大型项目难以管理。
服务器端的NodeJS遵循CommonsJS规范,该规范核心思想是允许模块通过require方法来同步加载所需依赖的其它模块,然后通过exports或module.exports来导出需要暴露的接口。
安装webpack
npm install webpack -g
npm install webpack-cli -g
下载完成之后,创建IDEA项目(建一个新文件夹,然后open)
1创建一个modules目录,放置JS模块等资源
2在该目录创建一个js文件,比如hello.js
1
2
3
4
|
//暴露第一个方法:sayHi
exports.sayHi=function () {
document.write("<div>hellow webpack</div>");
}
|
3写main.js
1
2
|
var hello=require("./hello");
hello.sayHi();
|
4写web.config.js
1
2
3
4
5
6
|
module.exports={
entry:'./modules/main.js',
output:{
filename: "./js/bundle.js"
}
}
|
5在IDEA的Terminal输入webpack进行打包,如果失败,可以按照提示命令进行处理。
webpack ‘modules/main.js’ -o ‘./js/bundle.js’ 也可以用这个命令。第一个是入口的js,第二个是打包位置
可以带上参数webpack --watch用于监听项目变化,热部署。
==npm run dev==启动项目
第三章 Vue-cli高级
1Router路由
路由的使用需要进行下载(安装),然后导入,再进行使用
1环境安装
vue-router是个插件包用npm/cnpm进行安装。
在项目目录输入:==npm install vue-router --save-dev== –save-dev意思在package.josn的devDependencies保存。(去掉dev是生产环境)
在node_modules下面找到router说明安装好了。
第一步,查看文件结构:src下面assets为空,components也可以为空,只剩下main.js和App.vue。下面解释这两个文件
文件结构。
1
2
3
4
5
6
7
8
9
10
11
12
|
//main.js 这里我们看到创建了一个app
import Vue from 'vue'
import App from './App'
Vue.config.productionTip = false //是个开发提示 也可以删掉
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
template: '<App/>'
})
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
//App.vue
<template>
<div id="app">
</div>
</template>
<script>
//导出 给main.js引用
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>
|
2父子组件
第二步,npm run dev可以运行一下,然后我们修改app.vue的div,在里面加点数据比如hello world,再次查看页面,发现没有刷新马上改变了,这就是热部署。
第三步,写一个自己的组件,在components下新建一个Compoent.vue组件,然后仿照app.vue写一个自己的组件如:t1.vue scoped/skoʊp/是范围的意思,就是局部的style
注意==template标签下的内容必须被一个容器包裹(比如div),仅有一个时例外==
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<template>
<h1>内容页</h1>
</template>
<script>
export default {
name: "t1"
}
</script>
<style scoped>
</style>
|
写了这样一个组件,我们要放到app.vue去使用这个自己写的组件。
只需要在依赖这个组件的父组件,import导入,然后components:{‘使用时标签名’:导入的别名,'':别名},这里只是做为一个演示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
//vue.js这里只是演示如何引用组件,做为了解。
<template>
<div id="app">
<h1>又一次相遇1了</h1>
<t1></t1>
<main2></main2>
</div>
</template>
<script>
import t1 from './components/t1'
import main from './components/main'
export default {
name: 'App',
components:{
't1':t1,'main2':main
}
}
</script>
|
3写路由
在src下新建一个router文件夹,写一个index.js主配置文件(以后看到的index可能是主页也可能是主配置文件)
路由是vue下的组件所以要导入vue,我们使用路由,要导入路由,然后我们要把自己写的组件注册到路由中,要导入我们的组件。
然后安装路由,最后路由是给别人使用的,所有要导出配置。当我们继续注册路由组件时候,1写组件,然后在这个文件中导入,2routes中注册(有点像springMVC的mapping)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
//index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
//导入自己写的组件
import main from '../components/main'
import HelloWorld from "../components/HelloWorld";
//安装路由
Vue.use(VueRouter);
//配置 导出路由
export default new VueRouter({
mode:'history',
routes:[
{
//路由路径
path:'/main',
//跳转的组件
component:main
},
{
//路由路径
path:'/hello',
//跳转的组件
component:HelloWorld
}
]
});
//导出路由还有一种写法,export default 对象名称
|
4使用路由
使用路由很简单<router-link to=”/main">首页</router-link>就相当于a标签,router-view是显示路由的页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//app.vue
<template>
<div id="app">
<h1>又一次相遇1了</h1>
<router-link to="/main">首页</router-link>
<router-link to="/hello">HelloWorld</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
|
5嵌套路由
1
2
3
4
5
6
7
8
|
/user/foo/profile /user/foo/posts
+------------------+ +-----------------+
| User | | User |
| +--------------+ | | +-------------+ |
| | Profile | | +------------> | | Posts | |
| | | | | | | |
| +--------------+ | | +-------------+ |
+------------------+ +-----------------+
|
所有的页面都是在App.vue中显示的,用路由显示,只需要为其加一个<router-view>,然后在router/index.js中注册就好了,
App.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
//App.vue
<template>
<div id="app">
<h1>又一次相遇1了</h1>
<!-- <router-link to="/main">首页</router-link>-->
<router-view></router-view>
</div>
</template>
<script>
import t1 from './components/t1'
import main2 from './components/main'
export default {
name: 'App',
}
</script>
|
嵌套路由的意思是,在显示的页面比如t1,再去进行一个嵌套。
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
//index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
//导入自己写的组件
import main from '../components/main'
//main的子路由
import Content1 from '../components/content/Content1'
import Content2 from '../components/content/Content2'
//安装路由
Vue.use(VueRouter);
//配置 导出路由
export default new VueRouter({
routes:[
{
//路由路径
path:'/main',
//跳转的组件 children是main下的嵌套路由
component:main ,
children:[
{path:'/content/content1',component:Content1},
{path:'/content/content2',component:Content2}
]
},
]
});
|
main.vue 中嵌套的两个路由。将在router-view中显示。(main.js和content.vue 都是App.vue下的)
1
2
3
4
|
<router-link to="/content/content1">内容页1</router-link>
<router-link to="/content/content2">内容页2</router-link>
<router-view></router-view>
|
6参数传递
当我们想通过路由传递参数时。
方式一:耦合度高,不推荐使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
======传递信息的页面main.vue============
<!--链接页面,main.vue,要向第二个页面传递信息
不传递信息时:直接to="index中的path就好了比如/content/content2"
-->
<router-link v-bind:to="{name:'content1',params:{id:1,name:'卢森林'}}">
个人信息
</router-link>
=======路由配置index.js=====================================
routes:[
{
//路由路径
path:'/main',
//跳转的组件 children是main下的嵌套路由
component:main,
children:[
{path:':id/:name',name:'content1',component:Content1},
{path:'/content/content2',component:Content2}
]
},
=========Content1信息接受页面=========================
<template>
<div>
<h1>用户信息</h1>
<p>{{$route.params.id}}</p>
<p>{{$route.params.name}}</p>
</div>
</template>
|
方式二: 在方式一基础上,传递页面不用改
1 index.js的path属性加上props:true
2 Content1.vue加上props:[‘id’,‘name’],取出直接[[id]]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
=======路由配置index.js=====================================
routes:[
{
//路由路径
path:'/main',
//跳转的组件 children是main下的嵌套路由
component:main,
children:[
{path:':id/:name',name:'content1',component:Content1,props:true},
{path:'/content/content2',component:Content2}
]
}]
======取出Content1.vue===========
<template>
<div>
<h1>用户信息</h1>
<p>{{id}}</p>
<p>{{name}}</p>
</div>
</template>
<script>
export default {
props:['id','name'],
name: "Comtent1"
}
</script>
|
当我们传递参数到一个路由时,而不是嵌套路由。
1这是表单成功时,手动跳转。
1
2
|
//使用vue-router 路由到指定页面,该方式称之为编程式路由
this.$router.push("/main/"+this.ruleForm.pass) ;
|
2index.js路由配置页面,要path接受参数,还要props: true
1
2
3
4
5
6
7
8
9
10
11
|
{
//路由路径
path:'/main/:pass',
props:true,
//跳转的组件 children是main下的嵌套路由
component:main,
children:[
{path:':id/:name',name:'content1',component:Content1,props:true},
{path:'/content/content2',component:Content2}
]
},
|
3main.vue中取出
使用{{pass}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<script>
export default {
name: "main2",
props: ['pass'],
methods: {
handleOpen(key, keyPath) {
console.log(key, keyPath+"=========");
},
handleClose(key, keyPath) {
console.log(key, keyPath);
}
}
}
</script>
|
7重定向
this.$router.push("/Home”);//比如提交表单成功后进行跳转。跳转到router中的Home
路由相当于转发,地址栏不会发生改变,若想重定向的话。
只需要在index.js路由配置中用redirect关键字就好,
1
2
3
4
5
6
7
8
9
10
11
12
|
{
//路由路径
path:'/t1',
//转发的组件
component:t1
},
{
//路由路径
path:'/gohome',
//重定向的组件
redirect:"/t1"
}
|
8页面404
在index.js路由配置页面,配置一个自己写的NoFound页面就好。
1
2
3
4
5
6
|
{
//404 路由路径
path: '*',
//跳转的组件
component: NoFound
}
|
9钩子函数/路由护卫
beforeRouteEnter: (to, from, next) =>{}进入路由之前执行的函数
beforeRouteLeave: (to, from, next) =>{}离开路由之前执行的函数
●to:路由将要跳转的路径信息
●from:路径跳转前的路径信息
●next: 路由的控制参数
●next() 跳入下一个页面
●next('/path’)改变路由的跳转方向,使其跳到另一个路由
● next(false)返回原来的页面
●next((vm)=>{})仅在beforeRouteEnter中可用,vm是组件实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
<script>
export default {
name: "main2",
props: ['pass'],
methods: {
handleOpen(key, keyPath) {
console.log(key, keyPath+"=========");
},
handleClose(key, keyPath) {
console.log(key, keyPath);
}
},
//进入路由之前执行的钩子函数,
beforeRouteEnter: (to, from, next) =>{
console.log("进入路由前");
next();
},
//离开路由 执行的钩子函数,
beforeRouteLeave: (to, from, next) =>{
console.log("离开路由后");
next();
}
}
</script>
|
路由护卫
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
//挂载路由守卫
myRouter.beforeEach((to,from,next)=>{
const userFlag=$cookies.get("user");//取出当前用户
if(to.path=='/login'){
if(userFlag){
return next('/home')
};
return next() //若是登录页面则放行
}
if(!userFlag){
return next('/login') //若不存在,则跳转登录
}
//其它情况放行
return next()
})
export default myRouter
|
this.$router.push({path:"/home"})
路由跳转
2vue-cookies
除了cookie若是只存在当前会话中(关闭浏览器就消失)
1
2
3
4
5
6
7
8
|
//存入sessionStorage
window.sessionStorage.setItem("user",this.loginForm.username)
//取出
window.sessionStorage.getItem("user")
//清除
window.sessionStorage.clear()
|
关于目录等https://www.jianshu.com/p/8deae75624eb
具体和时间操作:https://www.jianshu.com/p/60c13168cc8f
1首先下载npm install vue-cookies –save
1
2
3
4
5
6
7
8
9
|
/* import VueCookies from 'js-cookie'
下面的vue-cookies可以使用use方式,也可以使用prototype方式,
router下的不能加this,因为这个this并不是指向的vue。$cookies.get
其它组件可以加也可以不加
*/
import VueCookies from 'vue-cookies'
Vue.use(VueCookies)
|
全局设置以及使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
//设置过期时间
this.$cookies.config(expireTimes[,path]) // default: expireTimes = 1d , path=/
//设置一个cookie
$cookies.set("user","卢森林","30min")
this.$cookies.set(keyName, value[, expireTimes[, path[, domain[, secure]]]]) //return this
//获取
this.$cookies.get(keyName) // return value
//删除
this.$cookies.remove(keyName [, path [, domain]]) // return this
//检查是否存在
this.$cookies.isKey(keyName) // return false or true
|
设置过期时间,输入字符串类型(字符均忽略大小写):
Unit |
full name |
y |
year |
m |
month |
d |
day |
h |
hour |
min |
minute |
s |
second |
第四章-Vuex
Vuex四大属性:state,getter,action,mutations
1state相当于是一个容器,里面可以放置数据。有点类似date
2getter相当于是计算属性,它的返回值会根据它的依赖被缓存,只有当依赖值改变才会重写计算,它用来监听属性值的变化,返回计算后的结果。
3actions用来调用mutations的方法,在actions中提交mutation再去修改状态值。
4mutations用来修改store中的值
使用前要进行导入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
// 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'
//1导入axios
import myAxios from "axios"
//2使用axios
Vue.prototype.$axios=myAxios
Vue.config.productionTip = false
//路由
import vueRouter from "@/router/index.js"
//1导入 2使用vuex
import vuex from 'vuex'
Vue.use(vuex)
//可以抽取出来 store文件下的Index
//在下面Vue实例中导入
let store=new vuex.Store({
state:{
amount:0,
name:'main.js初始值'
},
mutations:{
addAmount:function(state){
state.amount=state.amount+1
},
minusAmount:function(state){
state.amount=state.amount-1
},
changeName(state,name){
state.name=name
}
},
actions:{
addAmountAction(store){
store.commit('addAmount')
},
minusAmountAction(store){
store.commit('minusAmount')
},
changeName(store,name){
store.commit('changeName',name)
}
},
getters:{
getAmount(state){
return "¥"+parseFloat(state.amount*10).toFixed(2)
}
}
})
import mystore from './store/index.js'
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
store:mystore,
template: '<App/>',
router:vueRouter
})
|
想要修改state中数据,在vue页面中使用
this.$store.dispatch(‘addAmountAction’,参数)进行修改。
若是有参数,直接传参就好。(多参数用对象数组,仅能传递一个参数)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
<template>
<div>
<p>hello my name is Dept.vue!!!</p>
<p>部门页面</p>
<hr/>
<button v-on:click="addA()">+</button>
<button v-on:click="minusA()">-</button>
<p>取出amount:{{this.$store.state.amount}}</p>
<p>取出amount:{{this.$store.getters.getAmount}}</p>
</div>
</template>
<script>
export default{
name:"dept",
//data(){
data:function(){
return {
a1:[]
}
},
methods:{
addA(){
this.$store.dispatch('addAmountAction')
},
minusA(){
this.$store.dispatch('minusAmountAction')
}
}
}
</script>
|
可以直接使用的:https://www.jianshu.com/p/4440c89a0ad5
下面的方法会报错
第一步:找到vue-devtools的github项目,并将其clone到本地. vue-devtools
1
2
3
4
5
6
7
8
9
10
|
git clone https://github.com/vuejs/vue-devtools.git
#然后去vue-devtools下运行
cnpm install
#第二步修改shells下的chrome下的manifest.json文件
#把"persistent":false改成true
#第三步编译代码
npm run build
|
第四步:扩展Chrome插件
Chrome浏览器 > 更多程序 > 拓展程序
点击加载已解压程序按钮, 选择 vue-devtools > shells > chrome 放入
注意:
vue项目, 打开f12, 选择vue就可以使用了.
1.vue必须引入开发版, 使用min压缩版是不能使用devtools进行调试的
2.安装后, 需要关闭浏览器, 再重新打开, 必须是vue项目才能使用
第六章优化
1优化(Linux)
打包报告
npm intall webpack-bundle-analyzer –save-dev下载插件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
//webpack 可视化资源大小
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
lintOnSave: false,
devServer: {
port: 8019
},
productionSourceMap: false,
configureWebpack: {
plugins: [
new CompressionPlugin({
filename: "[path].gz[query]",
algorithm: "gzip",
test: /\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8,
deleteOriginalAssets: false//是否删除原文件
}),
new BundleAnalyzerPlugin()
],
|
执行npm run build–report 可以查看占用情况。(实际上用Vue-ui打开的项目就以可看到依赖)
执行npm run build 可以看到dist文件夹下有文件生成
1优化map,在config文件下设置productionSourceMap: false(出错快速定位位置)剔除.js.map,减少打包体积
2减少js体积
1
2
3
4
5
6
|
dist\js\chunk-vendors.86a67fa7.js 852.13 KiB 229.40 KiB
dist\js\app.e9b42a20.js 22.99 KiB 5.86 KiB
dist\js\chunk-43959ab3.d42aed8e.js 4.06 KiB 1.82 KiB
dist\css\chunk-vendors.2ac5db4b.css 204.88 KiB 32.80 KiB
dist\css\chunk-43959ab3.d63b84fe.css 1.54 KiB 0.61 KiB
dist\css\app.4a7c53d3.css
|
可以看到3个js文件,chunk-vendors提取公共模块提取的代码块,webpack本身带的模块代码部分、app入口文件、在vendors基础上抽取常变动的部分chunk
比如:使用element-ui那么就可以去官网上去按需引入
外部CDN资源
默认情况下,通过import语法导入的第三方依赖包,最终会被打包合并到同一个文件中,从而导致打包成功
后,单文件体积过大的问题。
为了解决上述问题,可以通过webpack的externals 节点,来配置并加载外部的CDN资源。凡是声明在externals中的第三方依赖包,都不会被打包。
1具体配置代码(引入CDN外部资源)
在public下的index.html下引入外部资源,注意:要剔除main.js下的import,否则会导入两次。element-ui的vue也可以不用
注意版本号
1
2
3
|
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.runtime.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.13.2/index.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/element-ui/2.13.2/theme-chalk/index.css" rel="stylesheet">
|
2vue.config.js进行设置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
//webpack gzip的设置
var CompressionPlugin = require("compression-webpack-plugin");
module.exports = {
lintOnSave: false,
devServer: {
port: 8019
},
productionSourceMap: false,
configureWebpack: {
plugins: [
new CompressionPlugin({
filename: "[path].gz[query]",
algorithm: "gzip",
test: /\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8,
deleteOriginalAssets: false//是否删除原文件
})
],
externals: {
//名称带中横线的需使用引号包起来,elementui需要导入vue的cdn
'ElementUI': 'ELEMENT',
vue: 'Vue',
// 'vue-router' : 'VueRouter',
// 'axios': 'axios',
// 'normalize':'Normalize',
// vuex:'Vuex'
}
}
}
|
Gzip优化
插件网址https://github.com/webpack-contrib/compression-webpack-plugin可以查看最新版本的配置等
1用gzip压缩(cli4)
1下载npm install compression-webpack-plugin -S
2vue.config.js设置 (注意,cli4以下版本,拥有Build文件夹的在/build/webpack.prod.config.js:下修改,还需要在vue.config.js中设置开启productionGzip: true,这个一般在服务器中开启)
3compression-webpack-plugin的版本3.0以下使用asset 高版本用filename
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//webpack gzip的设置
var CompressionPlugin = require("compression-webpack-plugin");
module.exports = {
lintOnSave: false,
devServer: {
port: 8019
},
productionSourceMap: false,
configureWebpack: {
plugins: [
new CompressionPlugin({
filename: "[path].gz[query]",
algorithm: "gzip",
test: /\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8,
deleteOriginalAssets: false//是否删除原文件
})
]
}
}
|
模拟上线
下载npm i -g http-server
hs -o -p 8885
要开启服务