vueAPI
# 教程
2019Vue、Vuejs最详细教程-入门到项目实战 (opens new window)
# Vue实例传入的options
<script type="text/javascript">
const app = new Vue({
el:'#app',//确定管理的DOM(string/HTMLElement)
//组件中,data必须是个函数
data:{
//存放数据(Object/Function)
message:'Hello Vue',
arr : ['生活','心情','日记','天空']
},
methods:{
//定义的方法
add:function(){},
sub:function(){},
},
//计算属性
computed:{
fullName:function(){
return this.firstName + ' ' + this.lastName
},
//注册组件
components:{
cpn
},
//生命周期
created:function(){},
mounted:function(){}
})
</script>
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
# 什么是MVVM?
■view层: 视图层
在我们前端开发中,通常就是DOM层
主要的作用是给用户展示各种信息
■Mode层:数据层 数据可能是我们固定的死数据,更多的是来自我们服务器,从网络上请求下来的数据。
在我们计数器的案例中,就是后面抽取出来的obj,当然,里面的数据可能没有这么简单。
■ VueModel层:视图模型层 视图模型层是vew和Mode沟通的桥梁。
一方面它实现了 Data Binding,也就是数据绑定,将Mode的改变实时的反应到vew中
另一方面它实现了 DOM Listener,也就是DOM监听,当DOM发生一些事件(点击、滚动、touch等)时,可以监听到,并在需要的情况下改变对应的Data。
# 计算属性
简单用法:
<div id="app">
<h2>{{firstName}} {{lastName}}</h2>
<!--传入的是对象,不加小括号-->
<h2>{{fullName}}</h2>
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
firstName:'Lebron',
lastName:'James'
},
//计算属性
computed:{
fullName:function(){
return this.firstName + ' ' + this.lastName
}
}
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
复杂用法:
<div id="app">
总价格:{{totalPrice}}
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
books:[
{id:110,name:'西游记',price:15},
{id:111,name:'水浒传',price:47},
{id:112,name:'红楼梦',price:45},
{id:113,name:'三国演义',price:26},
]
},
computed:{
totalPrice:function(){
let result = 0
// for (let i=0; i<this.books.length; i++){
// result += this.books[i].price
// }
//es6语法
// for (let i in this.books){
// result += this.books[i].price
// }
for (let book of this.books){
result += book.price
}
return result
}
}
})
</script>
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
计算属性的setter和getter:
//计算属性一般是没有set方法,只读属性
computed:{
// fullName:{
// get:function(){
// return this.firstName + ' ' + this.lastName
// }
// }
//下面是简写
fullName:function(){
return this.firstName + ' ' + this.lastName
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
计算属性和 methods的对比:
- methods和 computed看起来都可以实现我们的功能,
- 那么为什么还要多一个计算属性这个东西呢?
- 原因:计算属性会进行缓存,如果多次使用时,计算属性只会调用一次
# Mustache语法-插值操作(双大括号)
Mustache:胡子/胡须
<div id="app">
<h2>{{message}}</h2>
<h2>{{name_one}} {{name_two}}</h2>
<h2>{{name_one + ' ' + name_two}}</h2>
<h2>{{counter *2}}</h2> //200
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
name_one:'jack',
name_two:'john',
counter:100
}
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 插值操作-其它指令
# v-once
只渲染一次,不随数据改变
<div id="app">
<h2>{{message}}</h2>
<h2 v-once>{{message}}</h2> <!--只渲染一次,不随数据改变 -->
</div>
2
3
4
# v-html
可以渲染html代码
<!-- 可以渲染html代码-->
<div id="app">
<h2>{{url}}</h2> <!-- <a href="http://www.baidu.com">百度一下</a> -->
<h2 v-html="url"></h2> <!-- 百度一下 -->
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
url:'<a href="http://www.baidu.com">百度一下</a>'
}
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# v-text
与mustache语法类似
<!-- 与mustache语法类似 -->
<div id="app">
<h2>{{message}}</h2> <!-- 你好Vue -->
<h2 v-text="message"></h2> <!-- 你好Vue -->
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue'
}
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# v-pre
不解析mustache语法,原样输出
<!--不解析mustache语法-->
<div id="app">
<h2>{{message}}</h2> <!-- 你好Vue -->
<h2 v-pre>{{message}}</h2> <!-- {{message}} -->
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue'
}
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# v-cloak
cloak:斗篷
在vue解析之前,div中有一个属性 v-cloak 在vue解析之后,属性v-cloak消失
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style type="text/css">
/* 设置隐藏 */
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<h2>{{message}}</h2>
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
//在vue解析之前,div中有一个属性v-cloak
//在vue解析之后,div中没有一个属性v-cloak
setTimeout(function(){
const app = new Vue({
el:'#app',
data:{
message:'你好Vue'
}
})
},2000)
</script>
</body>
</html>
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
# v-bind:属性/:属性 动态绑定属性
基本使用:
<div id="app">
<!--<img v-bind:src="imgurl">
<a v-bind:href="aUrl">百度一下</a> -->
<img :src="imgurl">
<a :href="aUrl">百度一下</a>
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
imgurl:'https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/7c5524bbd8d8e2d8b4fec3774915d2fb.jpg',
aUrl:'http://ww.baidu.com'
}
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# v-bind动态绑定class(对象语法)
<div id="app">
<!-- class中传入对象 -->
<!-- <h2 :class="{类名1:true,类名2:false}">{{message}}<h2> -->
<h2 :class="{active:isActive,line:isLine}">{{message}}<h2>
<!-- 传入方法 -->
<h2 :class="getClasses()">{{message}}<h2>
<button @click="btnClick">切换</button>
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
isActive:false,
isLine:true
},
methods:{
btnClick:function(){
this.isActive = !this.isActive
},
getClasses:function(){
return {active:this.isActive,line:this.isLine}
}
}
})
</script>
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
# v-bind动态绑定style(对象语法)
<div id="app">
<!-- <h2 :style="{key(属性名):value(属性值)}">{{message}}</h2> -->
<!-- '50px'表示字符串,50px会被解析成变量 -->
<!-- <h2 :style="{fontSize:'50px'}">{{message}}</h2> -->
<h2 :style="{fontSize:finalSizeA}">{{message}}</h2>
<h2 :style="{fontSize:finalSizeB + 'px', color:finalColor}" >{{message}}</h2>
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
finalSizeA:'50px',
finalSizeB:50,
finalColor:'red'
}
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# v-on:click/@click 监听点击事件
# 案列:计数器
<div id="app">
<h2>当前计数{{counter}}</h2>
<!--<button type="button" v-on:click="counter++">+</button>
<button type="button" v-on:click="counter--">-</button> -->
<button type="button" v-on:click="add">+</button>
<button type="button" @click="sub">-</button>
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
counter:0
},
methods:{
add:function(){
console.log('add执行');
this.counter++
},
sub:function(){
console.log('sub被执行');
this.counter--
}
}
})
</script>
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
# v-on的参数传递
<div id="app">
<!-- 事件调用的方法没有参数 -->
<button @click="btn1Click()">按钮1</button>
<button @click="btn1Click">按钮2</button> <!-- 没有参数,括号可省略 -->
<button @click="btn2Click('jack')">按钮3</button> <!-- ---- jack -->
<button @click="btn2Click()">按钮4</button> <!-- ---- undefined -->
<button @click="btn2Click">按钮5</button> <!-- MouseEvent对象 -->
<!-- 同时需要event对象和其它参数 -->
<!-- $event--手动获取event对象 -->
<button @click="btn3Click('jack',$event)">按钮6</button>
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
},
methods:{
btn1Click:function(){
console.log("btn1Click")
},
btn2Click:function(name){
console.log("----",name)
},
btn3Click:function(name,event){
console.log("----",name,event)
}
}
})
</script>
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
# v-on的修饰符
- .stop修饰符,阻止冒泡
- .prevent修饰符,阻止默认事件
- @keyup.enter(或者键的编码)监听某个键盘的键帽弹起
- .once 只能执行一次
<div id="app">
<!-- .stop修饰符,阻止冒泡 -->
<div @click="divClick">
aaaa
<!-- .stop修饰符,阻止冒泡,只让按钮的方法生效 -->
<button @click.stop="btnClick">按钮</button>
</div>
<!-- .prevent修饰符,阻止默认事件 -->
<form action="baidu" >
<!-- 阻止自动提交 -->
<input type="submit" value="提交" @click.prevent="submitClick"/>
</form>
<!-- @keyup.enter(或者键的编码)监听某个键盘的键帽 -->
<!-- 监听回车键的弹起 -->
<input type="text" @keyup.enter="keyUp">
<!-- .once 只能执行一次 -->
<button type="button" @click.once="btn2Click">一次性按钮</button>
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue'
},
methods:{
btnClick(){
console.log("btnClick")
},
divClick(){
console.log("divClick")
},
submitClick(){
console.log('submitClick')
},
keyUp(){
console.log('keyUp')
},
btn2Click(){
console.log('btn2Click')
}
}
})
</script>
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
#
# v-if和v-else-if和v-else使用
<div id="app">
<div v-if="isShow">------这是v-if显示------</div>
<div v-else>-----这是v-else显示------</div>
<button type="button" @click="isShow = !isShow">切换</button>
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
isShow:true
}
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 小案例:切换登录方式
<div id="app">
<!-- {{message}} -->
<span v-if="isUser">
<label for="username">用户账户</label>
<!-- 加上key,处理DOM复用的问题 -->
<input type="" name="" id="username" value="" placeholder="用户账户" key="username"/>
</span>
<span v-else>
<label for="userEmail">用户邮箱</label>
<input type="" name="" id="userEmail" value="" placeholder="用户邮箱" key="userEmail"/>
</span>
<button type="button" @click="change">切换登录</button>
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const vue = new Vue({
el:"#app",
data:{
message:"你好,Vue",
isUser:true
},
methods:{
change(){
return this.isUser = !this.isUser
}
}
})
</script>
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
# 案例input的问题
如果我们在有输入内容的情况下,切换了类型,我们会发现文字依然显示之前的输入的内容。
但是按道理讲,我们应该切换到另外一个 input元素中了
在另一个input元素中,我们并没有输入内容
为什么会出现这个问题呢? ■问题解答:
这是因为ue在进行DOM道染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素
在上面的案例中,Vue内部会发现原来的 input元素不再使用,直接作为else中的 input来使用了 ■解决方案 如果我们不希望Vue出现类似重复利用的问题,可以给对应的 input添加key
并且我们需要保证key的不同
# v-for 列表展示
# 遍历数组
<div id="app">
<ul>
<!--将arr数组循环遍历-->
<li v-for="(item,index) in arr">{{index+1}}----{{item}}</li>
</ul>
</div>
<template>
</template>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
arr : ['生活','心情','日记','天空']
}
})
</script>
输出:
1----生活
2----心情
3----日记
4----天空
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 遍历对象
<div id="app">
<!-- 1.在遍历对象的过程中,如果只是获取一个值,那么获取到的是value -->
<ul>
<li v-for="item in info" :key="item">{{item}}</li>
</ul>
<!-- 2.获取key和value (value,key)-->
<ul>
<li v-for="(value,key) in info">{{key}}----{{value}}</li>
</ul>
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
info :{
name:'jack',
age:18,
height:1.88
}
}
})
</script>
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
# 数组中哪些方法是响应式的?
<div id="app">
<ul>
<li v-for="item in letters" >{{item}}</li>
</ul>
<button type="button" @click="btnClick">按钮</button>
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
letters:['a','b','c','d']
},
methods:{
btnClick(){
//通过索引值修改数组中的元素
// this.letters[0] = 'bbb'
// 1.push方法--末尾添加元素,可以添加多个元素
// this.letters.push('aaa')
//this.letters.push('aaa','bbb','ccc')
//2.pop方法----删除末尾的元素
// this.letters.pop()
// 3.shift方法---删除开头的元素
// this.letters.shift()
//4.unshift方法---在开头添加
// this.letters.unshift('aaaa')
//5.splice方法---作用:删除元素/插入元素/替换元素
//删除元素:第二个参数传入要删除几个元素
//splice(start,删除个数)
// this.letters.splice(1,1)
//替换元素 b,c,d => x,y,z
// this.letters.splice(1,3,'x','y','z')
//插入元素:第二个参数,传入0,后面跟上要插入的元素
//a和b之间插入 m
// this.letters.splice(1,0,'m')
//6.sort方法---排序
// this.letters.sort()
//7.reverse方法---反转
// this.letters.reverse()
//Vue中的set方法--替换
Vue.set(this.letters,0,'bbbb')
}
}
})
</script>
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
# 案例:列表选中激活
<div id="app">
<ul>
<li v-for="(book,index) in books" :class="{active:isActive(index)}" @click="liClick(index)">{{index}}--{{book}}</li>
</ul>
</div>
<script src="vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
books:['水浒传','三国演义','红楼梦','西游记'],
currentIndex:0
},
methods:{
isActive(index){
return index === this.currentIndex
},
liClick(index){
this.currentIndex = index
}
}
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# v-model表单绑定
# input类型
<div id="app">
<!-- <input type="text" v-model="message"> -->
<!-- 事件绑定 -->
<!-- <input type="text" @input="valueChange" :value="message"> -->
<!-- <input type="text" :value="message" @input="message = $event.target.value"> -->
<h2>{{message}}</h2>
</div>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:''
},
methods:{
valueChange(event){
this.message = event.target.value;
}
}
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# radio类型
<div id="app">
<label for="male">
<!-- name相同时,只能选一个,有v-model时 name可以省略 -->
<input type="radio" id="male" value="男" v-model="sex" name="sex">男
</label>
<label for="female">
<input type="radio" id="female" value="女" v-model="sex" name="sex">女
</label>
<h2>选择的性别是:{{sex}}</h2>
</div>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
sex:'男'
}
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# checkbox类型
<div id="app">
<!-- 1.checkbox单选框 -->
<label for="agree">
<input type="checkbox" name="" id="agree" value="" v-model="isAgree"/>同意协议
</label>
<h2>你选择的是:{{isAgree}}</h2>
<button type="button" :disabled="!isAgree">下一步</button>
<br>
<!-- 2.checkbox多选框 -->
<input type="checkbox" name="" id="" value="篮球" v-model="hobbies"/>篮球
<input type="checkbox" name="" id="" value="足球" v-model="hobbies"/>足球
<input type="checkbox" name="" id="" value="乒乓球" v-model="hobbies"/>乒乓球
<input type="checkbox" name="" id="" value="羽毛球" v-model="hobbies"/>羽毛球
<h2>爱好</h2>
<ul>
<li v-for="hobby in hobbies">{{hobby}}</li>
</ul>
<label v-for="item in originHobbies" :for="item">
<input type="checkbox" :id="item" :value="item" v-model="hobbies"/>{{item}}
</label>
</div>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
isAgree:false,//单选框
hobbies:[],//多选框,
originHobbies:['篮球','足球','铅球']
}
})
</script>
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
# select类型
<div id="app">
<!-- 1.选择一个 -->
<select name="abc" v-model="fruit">
<option value ="苹果">苹果</option>
<option value ="香蕉">香蕉</option>
<option value ="榴莲">榴莲</option>
<option value ="葡萄">葡萄</option>
</select>
<h2>你选择的是:{{fruit}}</h2>
<!-- 1.选择多个-->
<select name="abc" v-model="fruits" multiple>
<option value ="苹果">苹果</option>
<option value ="香蕉">香蕉</option>
<option value ="榴莲">榴莲</option>
<option value ="葡萄">葡萄</option>
</select>
<h2>你选择的是:{{fruits}}</h2>
</div>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
fruit:'苹果',
fruits:[]
}
})
</script>
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
# v-model修饰符
<div id="app">
<!-- 1.修饰符: .lazy -->
<!-- 让数据在失去焦点或者回车时才会更新 -->
<input type="text" v-model.lazy="message">
<h2>{{message}}</h2>
<!-- 2.修饰符: .number -->
<!-- 让在输入框中输入的内容自动转成数字类型 -->
<input type="number" v-model.number="age">
<h2>年龄:{{age}}----{{typeof age}}</h2>
<!-- 3.修饰符: trim -->
<!-- 去除内容两边的空格 -->
<input type="text" v-model.trim="name">
<h2>名字:{{name}}</h2>
</div>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'',
age:0,
name:''
}
})
</script>
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
# 组件化开发
步骤:
1.创建组件的构造器对象
2.注册组件
3.使用组件
# 基本使用
<div id="app">
//3.使用组件
<my-cpn></my-cpn>
</div>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
//1.创建组件的构造器对象
const cpnC = Vue.extend({
template:`
<div>
<h2>标题</h2>
<p>内容哈哈</p>
<p>内容呵呵呵</p>
</div>
`
})
//2.注册组件
// Vue.component('组件的标签名','构造器')
Vue.component('my-cpn',cpnC)
const app = new Vue({
el:'#app',
data:{
message:'你好Vue'
}
})
</script>
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
# 全局组件和局部组件
<div id="app">
<cpn></cpn>
</div>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
//1.创建组件的构造器对象
const cpnC = Vue.extend({
template:`
<div>
<h2>标题</h2>
<p>内容哈哈</p>
<p>内容呵呵呵</p>
</div>
`
})
//2.注册组件(全局组件,可以在多个Vue的实例下使用)
// Vue.component('组件的标签名','构造器')
// Vue.component('cpn',cpnC)
const app = new Vue({
el:'#app',
data:{
message:'你好Vue'
},
//局部组件
components:{
//cpn使用组件时的标签名
cpn:cpnC
}
})
</script>
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
# 父组件和子组件
<div id="app">
<cpn2></cpn2>
</div>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
//子组件
const cpnC1 = Vue.extend({
template:`
<div>
<h2>标题</h2>
<p>内容哈哈</p>
</div>
`
})
//父组件
const cpnC2 = Vue.extend({
template:`
<div>
<h2>标题</h2>
<p>内容呵呵呵</p>
<cpn1></cpn1>
</div>
`,
components:{
cpn1:cpnC1
}
})
const app = new Vue({
el:'#app',
data:{
message:'你好Vue'
},
components:{
cpn2:cpnC2
}
})
</script>
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
# 组件的语法糖注册方式
<div id="app">
<cpn1></cpn1>
<cpn2></cpn2>
</div>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
// 注册全局组件(语法糖)
Vue.component('cpn1',{
template:`
<div>
<h2>标题</h2>
<p>内容哈哈</p>
</div>
`
})
const app = new Vue({
el:'#app',
data:{
message:'你好Vue'
},
// 注册局部组件(语法糖)
components:{
'cpn2':{
template:`
<div>
<h2>标题</h2>
<p>内容呵呵</p>
</div>
`
}
}
})
</script>
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
# 组件中的data必须是函数
<div id="app">
<cpn1></cpn1>
</div>
<template id="cpn1">
<div>
<h2>{{title}}</h2>
<p>内容哈哈</p>
</div>
</template>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
// 注册全局组件
Vue.component('cpn1',{
template:'#cpn1',
//这里data必须是函数,否则会报错
data(){
return{
title:'abc标题'
}
}
})
const app = new Vue({
el:'#app',
data:{
message:'你好Vue'
}
})
</script>
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
# 组件通信----父传子(props)
<div id="app">
<!--2.绑定-->
<cpn :cmovies='movies'></cpn>
</div>
<template id="cpn">
<div>
<ul>
<li v-for="item in cmovies">{{item}}</li>
</ul>
</div>
</template>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
//父传子:props==>properties 属性
// 子组件
const cpn = {
template:'#cpn',
//1.定义
props:['cmovies'],
}
// 父组件(Vue实例)
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
movies:['海王','超人']
},
components:{
cpn
}
})
</script>
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
# props中的驼峰标识
<div id="app">
<!-- 不支持驼峰标识 cInfo转换为c-info,childMyMessage转换为child-my-message-->
<cpn :c-info="info"></cpn>
</div>
<template id="cpn">
<!-- 模板有多个标签时,必须包含根标签(例:div) -->
<div>
<h2>{{cInfo}}</h2>
</div>
</template>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const cpn = {
template:'#cpn',
props:{
//驼峰标识
cInfo:{
type: Object,
default(){
return{name:'某人'}
}
}
}
}
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
info:{
name:'jack',
age:18
}
},
components:{
cpn
}
})
</script>
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
# 组件通信---子传父(自定义事件名称)
<div id="app">
<!-- 2.监听事件 -->
<cpn @item-click="cpnClick"></cpn>
</div>
<template id="cpn">
<div>
<button type="button" v-for="item in categories" @click="btnClick(item)">
{{item.name}}
</button>
</div>
</template>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const cpn = {
template:'#cpn',
data(){
return{
categories:[
{id:'aaa',name:'热门推荐'},
{id:'bbb',name:'手机数码'},
{id:'ccc',name:'家用家电'},
{id:'ddd',name:'电脑办公'},
]
}
},
methods:{
btnClick(item){
//1.发射事件 this.$emit('自定义事件名称',item)
this.$emit('item-click',item)
}
}
}
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
},
components:{
cpn
},
methods:{
cpnClick(item){
console.log(item.name)
}
}
})
</script>
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
# 父子组件通信-结合双向绑定案例
<div id="app">
<cpn :number1="num1"
:number2="num2"
@number1change="number1change"
@number2change="number2change"/>
</div>
<template id="cpn">
<div>
<h2>props:{{number1}}</h2>
<h2>data:{{dnumber1}}</h2>
<!-- <input type="text" v-model="dnumber1"> -->
<input type="text" :value="dnumber1" @input="num1Input">
<h2>props:{{number2}}</h2>
<h2>data:{{dnumber2}}</h2>
<!-- <input type="text" v-model="dnumber2"> -->
<input type="text" :value="dnumber2" @input="num2Input">
</div>
</template>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const cpn = {
template:'#cpn',
props:{
number1:Number,
number2:Number
},
data(){
return{
dnumber1:this.number1,
dnumber2:this.number2,
}
},
methods:{
num1Input(event){
//1.将input中的value赋值到dnumber中
this.dnumber1 = event.target.value
//2.为了让父组件可以修改值,发出一个事件
this.$emit('number1change',this.dnumber1)
},
num2Input(event){
this.dnumber2 = event.target.value
this.$emit('number2change',this.dnumber2)
},
}
}
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
num1:0,
num2:1
},
components:{
cpn
},
methods:{
number1change(value){
this.num1= parseFloat(value)
},
number2change(value){
this.num2= parseFloat(value)
}
}
})
</script>
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
# 组件访问--父访问子
<div id="app">
<!-- 加上ref -->
<cpn ref="aaa"></cpn>
<cpn></cpn>
<button type="button" @click="btnClick">按钮</button>
</div>
<template id="cpn">
<div>
我是子组件
</div>
</template>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const cpn = {
template:"#cpn",
methods:{
showMessage(){
console.log('这是子组件showMessage');
}
},
data(){
return{
name:'子组件name'
}
}
}
const app = new Vue({
el:'#app',
data:{
message:'你好Vue'
},
components:{
cpn
},
methods:{
btnClick(){
// 1.$children(使用较少)
// console.log(this.$children);
//调用子组件的方法
// this.$children[0].showMessage();
//调用子组件的属性
// console.log(this.$children[0].name);
//遍历
// for(let c of this.$children){
// console.log(c.name);
// c.showMessage()
// }
// 2.$refs
console.log(this.$refs.aaa.name)
}
}
})
</script>
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
# 组件访问--子访问父
<div id="app">
<cpn></cpn>
</div>
<template id="cpn">
<div>
我是cpn组件
<ccpn></ccpn>
</div>
</template>
<template id="ccpn">
<div>
<h2>我是子组件</h2>
<button type="button" @click="btnClick">按钮</button>
</div>
</template>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
//子组件
const ccpn = {
template:"#ccpn",
methods:{
btnClick(){
//1.访问父组件$parent(使用较少)
console.log(this.$parent.name);
//2.访问根组件$root(使用较少)--访问Vue实例
console.log(this.$root.message);
}
},
}
//父组件
const cpn = {
template:"#cpn",
components:{
ccpn
},
data(){
return{
name:'cpn组件的name'
}
}
}
const app = new Vue({
el:'#app',
data:{
message:'你好Vue'
},
components:{
cpn
}
})
</script>
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
# 组件化高级
# slot插槽的基本使用
<div id="app">
<cpn></cpn>
<cpn><span>添加</span></cpn>
<cpn><i>haha </i></cpn>
<cpn>
<del>aaa</del>
<del>bbbb</del>
<div>ccc</div>
</cpn>
</div>
<template id="cpn">
<div>
<h2>我是组件</h2>
<p>哈哈</p>
<!-- 插槽,可以放入默认值 -->
<slot><button type="button">按钮</button></slot>
</div>
</template>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好'
},
components:{
cpn:{
template:'#cpn'
}
}
})
</script>
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
# slot具名插槽
<div id="app">
<!-- 只会替换没有名字的插槽 -->
<cpn><span>标题</span></cpn>
<!-- 替换name为center的插槽 -->
<cpn><span slot="center">中间标题</span></cpn>
</div>
<template id="cpn">
<div>
<slot name="left"><span>左边</span></slot>
<slot name="center"><span>中间</span></slot>
<slot name="right"><span>右边</span></slot>
<slot>哈哈哈</slot>
</div>
</template>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好'
},
components:{
cpn:{
template:'#cpn'
}
}
})
</script>
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
# 什么是编译的作用域
<div id="app">
<!-- isShow使用的是实例中的,从当前模板中查找 -->
<cpn v-show="isShow"></cpn>
</div>
<template id="cpn">
<div>
<h2>我是子组件</h2>
<p>哈哈</p>
</div>
</template>
<script src="../vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
const cpn = {
template:"#cpn",
data(){
return{
isShow:false
}
}
}
const app = new Vue({
el:'#app',
data:{
message:'你好Vue',
isShow:true
},
components:{
cpn
}
})
</script>
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
# 作用域插槽
# Vue Mixins(混入)
作用:复用组件的功能
# 生命周期函数
注意:生命周期函数和methods同级,不要放在methods中
mounted 加载时执行
<script type="text/javascript">
const app = new Vue({
el:'#app',
data:{
message:'你好Vue'
},
beforeCreate:function(){
console.log('beforeCreate');
},
created:function(){
console.log('created');
},
mounted:function() {
console.log('mounted');
}
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 前端模块化
# ES6的模块化实现
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
// type="module"模块化
<script src="aaa.js" type="module"></script>
<script src="mmm.js" type="module"></script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
aaa.js
let name = '小明'
let age =18
let flag = true
function sum(num1,num2){
return num1+num2
}
//导出
export{
flag,
age,
sum
}
const address = '北京市'
//export default 导出(导入时,可以自己命名,只能有一个export default)
export default address
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mmm.js
//导入
import {flag, age, sum} from "./aaa.js"
import addr from "./aaa.js"
//全部导出,命名为aaa对象
import * as aaa from './aaa.js'
if(flag){
console.log(`${name}今年${age}岁了`);
console.log(sum(10,20));
}
//addr是自己命名的
console.log(addr)
//通过aaa对象取值
console.log(aaa.flag)
2
3
4
5
6
7
8
9
10
11
12
13
14
# Webpack
# 安装
安装webpack(指定版本号3.6.0,因为vue cli2依赖该版本)
-g 全局安装
npm install webpack@3.6.0 -g
局部(本地)安装
npm install webpack@3.6.0 --save -dev
--save -dev(--save 写入package.json,-dev开发时依赖)
打包
webpack / npm run build
//package.json
"scripts": {
"build": "webpack"//将webpack和npm run build对应,配置后,运行时,优先使用本地webpack
}
2
3
4
webpack.config.js
const path = require('path')
module.exports = {
entry:'./src/main.js',
output:{
path:path.resolve(__dirname,'dist'),
filename:'bundle.js'
}
}
2
3
4
5
6
7
8
9
项目初始化(安装node的包)
npm init
# Loader
npm install --save-dev less
npm install --save-dev less-loader
npm install --save-dev css-loader
npm install --save-dev style-loader
2
3
4
这些loader
的作用如下:
- 安装
less-loader
后可以在js
中使用require
的方式来加载less
文件了; - 安装
css-loader
后可以在js
中加载css
文件; - 安装
style-loader
的目的是为了让加载的css
作为style
标签内容插入到html
中。
# 配置loader
webpack.config.js代码如下:
module.exports = {
devtool: 'eval-source-map',
entry: __dirname + "/src/main.js", //入口文件
output: {
path: __dirname + "/dist", //打包后的文件存放的地方
filename: "bundle.js" //打包后输出文件的文件名
},
module: {
rules: [
{
test: /\.less$/,
use: ['style-loader','css-loader', 'less-loader']
}
]
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 引入图片 url -loader
module: {
rules: [
{
test: /\.(png|jpg|gif|jpeg)$/,
use: [{
loader:'url-loader',
option:{
limit:13000
}
}]
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
当加载的图片小于limit时,会将图片编译成base64字符串形式当加载的图片,
大于limit时,需要使用file-loader(需要安装,不用配置)模块进行加载。
# 脚手架创建Vue项目
根据package.json配置文件中的依赖配置下载安装 npm install
vue cli 3.0 安装cli npm i @vue/cli -g
vue create 项目名 **名字中不能有大写也不能用驼峰命名**
运行 npm run serve
vue cli 2.0 安装cli npm install -g @vue/cli-init
安装webpack npm **install** webpack -g
vue init webpack 项目名
运行 npm run dev
打包 npm run build
vue cli 4.0
打开可视化网页 vue ui
# 引入组件
import Header from './Header.vue';
components:{
'v-header':Header,
}
使用
<v-header></v-header>
# vue-resource 请求数据
1.安装
cnpm install vue-resource --save
//--save 表示加入package.json中
2.main.js 加入
import VueResource from 'vue-resource'
Vue.use(VueResource)
3.方法
methods:{
getData(){
//请求数据
var api = 'http://www.phonegap100.com/appapi.php?a=getPortalList&catid=20&page=1';
this.$http.get(api).then((response)=>{
window.console.log(response);
},(err)=>{
window.console.log(err);
})
}
}
2
3
4
5
6
7
8
9
10
11
4.展示
<ul>
<li v-for="item in list" :key='item'>
{{item.title}}
</li>
</ul>
2
3
4
5
网络请求 http://httpbin.org/ (opens new window)
http://123.207.32.32:8000/home/multidata (opens new window)
# axios 请求数据
vue全局使用axios的方法 (opens new window)
axios的使用小技巧:如何绕过字符串拼接,直接传递对象 (opens new window)
安装
npm install axios --save
引入(在main.js中)
import axios from 'axios' //也可以在组件中按需引入
Vue.prototype.$axios = axios; //使用原型的定理 将axios方法设定为Vue对象的方法(全局使用)
2
组件中使用
1.先设置跨域(/config/index.js中)
proxyTable: {
'/api': {
target: 'https://api.qq.jsososo.com/', //设置你调用的接口域名和端口号
changeOrigin: true, //跨域
pathRewrite: {
'^/api': '/'
//这里理解成用‘/api’代替target里面的地址,后面组件中我们调接口时直接用api代替 比如我要调用'http://10.1.5.11:8080/xxx/duty?id=3',直接写‘/api/xxx/duty? id=3’即可
},
}
},
2
3
4
5
6
7
8
9
10
2.组件中
<script type="text/javascript">
export default {
data() {
return {
qq_urls: []
}
},
methods: {
getList() {
this.$axios.get('/api/recommend/playlist').then(res => {
console.log(res.data)
var result = res.data.result
var list = res.data.data.list
if (result == 100) {
this.qq_urls = list
}
}).catch(err => {
console.log(err)
})
}
},
created: function() {
this.getList()
}
}
</script>
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
拼接url传递参数
<script type="text/javascript">
export default {
data() {
return {
singer:'周杰伦'
}
},
methods: {
getList() {
this.$axios({
methods:'get',
url:'/api/search',
//是params才能拼接到url上
params:{
key:this.singer
}
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
}
},
created: function() {
this.getList()
}
}
</script>
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
# 解决vue动态绑定audio/video的src不能播放
参考:http://www.fly63.com/article/detial/6914
<template>
<div>
<audio controls="controls" id="audioPlay" ref="audio">
</audio>
<input type="text" placeholder="输入链接id" v-model="music_id">
<button @click="getList()">播放</button>
</div>
</template>
<script type="text/javascript">
export default {
data() {
return {
music_id: '',
music_src: ""
}
},
methods: {
getList() {
this.$axios({
methods: 'get',
url: '/api/song/urls',
//是params才能拼接到url上
params: {
id: this.music_id
}
}).then(res => {
var result = res.data.result
//获取播放链接
const key = this.music_id
var music_url = res.data.data
if (result == 100) {
console.log(music_url[key])
//方法一
// let ado = document.getElementById("audioPlay")
// ado.src=music_url[key];
// ado.play();
//方法二
this.$refs.audio.src = music_url[key]
}
}).catch(err => {
console.log(err)
})
}
}
}
</script>
<style>
</style>
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
//1.axios的基本使用
axios({
url:'http://123.207.32.32:8000/home/multidata',
//默认get请求
methods:'get'
}).then(res =>{
console.log(res);
})
axios({
url:'https://api.uomg.com/api/rand.music',
params:{
sort:'热歌榜',
format:'json'
}
}).then(res =>{
console.log(res);
})
//2.axios发送 并发请求
axios.all([axios({
url:'http://123.207.32.32:8000/home/multidata'
}),axios({
url:'https://api.uomg.com/api/rand.music',
params:{
sort:'热歌榜',
format:'json'
}
})]).then(axios.spread((res1, res2) => {
console.log(res1);
console.log(res2);
}))
//3.使用全局配置进行网络请求
axios.default.baseURL = 'http://123.207.32.32:8000'
axios.default.timeout = 5000
axios.all([axios({
url:'/home/multidata',
}),axios({
url:'/data',
params:{
type: 'sell',
page:5
}
})]).then(axios.spread((res1, res2) => {
console.log(res1);
console.log(res2);
}))
// 4.创建对应的axios的实例
const instancel = axios.create({
baseURL:'http://123.207.32.32:8000',
timeout :5000
})
instancel({
url: '/home/multidata'
}).then(res =>{
console.log(res);
})
instancel({
url:'/home/data',
params:{
type:'pop',
page:1
}
}).then(res=> {
console.log(res)
})
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
# 非父子组件
src/model下创建 VueEvent.js,并添加
import Vue from 'vue'
var VueEvent = new Vue()
export default VueEvent
2
3
4
5
Home.vue 中,广播
<button @click="emitNews()">给News组件广播数据</button>
<script>
import VueEvent from '../model/vueEvent.js'
//方法
emitNews(){
//广播数据
VueEvent.$emit('to-news',this.msg)
}
</script>
2
3
4
5
6
7
8
9
10
News.vue中,接收
import VueEvent from '../model/vueEvent.js'
mounted(){
VueEvent.$on('to-news',function(data){
window.console.log(data);
})
}
2
3
4
5
6
7
# 双向绑定原理
vue
实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()
来劫持各个属性的 setter
,getter
,在数据变动时发布消息给订阅者,触发相应监听回调
https://www.bilibili.com/video/BV1oJ411t7zQ
let obj = {}
Object.defineProperty(obj,'val',{
get:function(){
console.log('ggg')
return 'xx123'
},
set:function(){
console.log('sss')
}
})
//写入时触发 set
obj.val = 123
//读取时触发 get
console.log(obj.val)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 自定义指令
导航点击高亮功能
https://www.bilibili.com/video/BV1dk4y1q7D7
src/view/doing/index.vue
<template>
<div class="nav-bar"
v-nav-current="{
curIdx,
className:'nav-item',
activeClass:'nav-current'
}">
指令
<!-- :class="['nav-item',{'nav-current':index === curIdx}]" -->
<div
class="nav-item"
v-for="(item, index) of items"
:key="index"
@click="changeNav(index)">
{{ item }}
</div>
</div>
</template>
<script>
import navCurrent from "@/directives/navCurrent";
export default {
name: "doing",
directives: {
navCurrent,
},
data() {
return {
curIdx: 0,
items: ["选项一", "选项二","选项三"],
};
},
methods:{
changeNav(index){
this.curIdx = index
}
}
};
</script>
<style scoped>
.nav-item{
background-color: #fff;
display: block;
width: 50px;
}
.nav-current{
background-color: rgb(110, 17, 17);
color: #fff;
}
</style>
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
src/directives/navCurrent.js
export default {
bind(el,binding, vnode){
const _ops = binding.value,
_c = el.getElementsByClassName(_ops.className)
_c[_ops.curIdx].className += ` ${_ops.activeClass}`
},
update(el,binding, vnode){
const _ops = binding.value,
_oOps = binding.oldValue,
_c = el.getElementsByClassName(_ops.className)
_c[_oOps.curIdx].className = `${_oOps.className}`
_c[_ops.curIdx].className += ` ${_ops.activeClass}`
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 核心业务
权限管理、上传类(视频、图片、表格)、下载/导出类(图片、Excel、PDF)、websocket类/第三方音视频sdk、echarts
# Vue优化
1、v-for 正确设置key值 2、封装复用的模块(http请求)、组件(ui库) 3、路由懒加载:component:() = import(./xxx.vue) 提高首屏加载速度 4、productionSourceMap: false config/index.js中 5、启用gzip压缩,打包体积更小 config/index.js中 6、keep-alive 缓存不活跃组件 7、插件CDN方式引入,减小项目体积 8、图片使用CDN地址,图片懒加载
# 解除严格模式
在build/webpack.base.conf.js中
// ...(config.dev.useEslint ? [createLintingRule()] : []),
...(config.dev.useEslint ? [] : []),
2
vue-cli4.0关闭eslint
在项目文件夹下新建一个文件vue.config.js,然后输入将下面的代码copy进入
module.exports = { lintOnSave: false };
1
2
3
4然后重新启动项目(一定要重启,不然不会生效)就可以了