vue
Vue全家桶
# 第1章:Vue核心
# 1.1. Vue的基本认识
# 1.1.1. 官网
英文官网: https://vuejs.org/
中文官网: https://cn.vuejs.org/
# 1.1.2. 介绍描述
渐进式JavaScript 框架
作者: 尤雨溪(一位华裔前Google工程师)
作用: 动态构建(显示 )用户界面
# 1.1.3. Vue的特点
遵循MVVM模式
编码简洁, 体积小, 运行效率高, 适合移动/PC端开发
它本身只关注视图层, 可以轻松引入vue插件或其它第三库开发项目
# 1.1.4. 与其它前端JS框架的关联
借鉴angular的**模板**和**数据绑定**技术
借鉴react的**组件化**和**虚拟DOM**技术
# 1.1.5. Vue扩展插件
vue-cli: vue脚手架
vue-resource(axios): ajax请求
vue-router: 路由
vuex: 状态管理
vue-lazyload: 图片懒加载
vue-scroller: 页面滑动相关
mint-ui: 基于vue的UI组件库(移动端)
element-ui: 基于vue的UI组件库(PC端)
# 1.2. Vue的基本使用
# 1.2.1 编码
<div id="app">
<input type="text" v-model="msg">
<p>{{msg}}</p>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.5.18/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app", //element 用来匹配模版的根元素
data:{
msg:"hello word" //为模板页面提供数据
}
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
# 1.2.2. 使用vue开发者工具调试
vue-Devtoos
# 1.2.3 . 理解MVC和Vue的MVVM
# 1.3. 模板语法
# 1.3.1. 模板的理解
html + js
js中以插值和指令形式存在
//插值
{{msg}}
//指令一: 强制数据绑定
完整写法:
v-bind:xxx='yyy' //yyy会作为表达式解析执行
简洁写法:
:xxx='yyy'
// 指令二: 绑定事件监听
完整写法:
v-on:click='xxx'
简洁写法:
@click='xxx' //xxx是事件名
2
3
4
5
6
7
8
9
10
11
12
- 实例:
<div id="app">
<a v-bind:href="url" >百度</a> //
<button v-on:click="test">测试按钮</button>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.5.18/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
msg:"hello word",
url:"https:www.baidu.com"
},
methods:{
test(){
console.log("text()")
}
}
})
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 1.4. 计算属性和监视
# 1.4.1 什么时候用计算属性
要显示的数据需要根据现有数据来计算
# 1.4.2. 计算属性computed
computed:{} //使用
实例代码
<div id="app">
<input type="text" v-model="firstName">
<input type="text" v-model="lastName">
<input type="text" v-model="fullName">
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.5.18/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
firstName:"zhang",
lastName:"san"
},
computed:{ //通过computed来实现数据的计算,默认是get
fullName(){
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
# 1.4.3. 计算属性高级getter/setter
computed:{
test:{ //test是自己定义的属性名
get(){ //get显示数据
},
set(value){ //set监视数据,value是传递过来的参数
}
}
}
2
3
4
5
6
7
8
代码实例
<div id="app">
<input type="text" v-model="firstName">
<input type="text" v-model="lastName">
<input type="text" v-model="fullName">
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.5.18/vue.js"></script>
<script type="text/javascript">
new Vue({
el:"#app",
data:{
firstName:"zhang",
lastName:"san"
},
//实现表单的双向绑定
computed:{
fullName:{
get(){ //get显示数据
return this.firstName+" "+this.lastName
},
set(value){ //set监视数据
const names=value.split(" ")
this.firstName=names[0]
this.lastName=names[1]
}
}
}
})
</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
# 1.4.4. 监视属性
通过通过vm对象的$watch()或watch配置来监视指定的属性
当属性变化时, 回调函数自动调用, 在函数内部进行计算
# 1.4.5. 实例代码
//方式一,Vue函数对象调用watch
watch:{
firstName(value){
this.fullName=value+" "+this.lastName
}
}
//方式二,通过vue实例对象调用watch
vm.$watch('firstName', function (value) {
this.fullName2 = this.firstName + '-' + value
})
2
3
4
5
6
7
8
9
10
# 1.5. class与style绑定
# 1.5.1. class绑定
1) :class='xxx' //完整版:v-bind:class
2) xxx: 'classA'
3) xxx: {classA:isA, classB: isB}
4) xxx: ['classA', 'classB']
2
3
4
5
6
7
# 1.5.2. style绑定
1) :style="{ color: activeColor, fontSize: fontSize + 'px' }"
2) 其中activeColor/fontSize是data属性
2
3
# 1.5.3. 代码实例
//class绑定中对象的方法
<style>
.active{
color: red;
}
</style>
<p :class="{active:hasA}">class样式</p> //active是对应style中的类名,其他自己定义
data:{
hasA:true //控制class类是否生效
}
//style绑定方法
<p :style="{color:activeColor,fontSize:activefont+'px'}">style样式</p>
data:{
activeColor:"blue",
activefont:20
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 1.6. 条件渲染
# 1.6.1. 条件渲染指令
1) v-if与v-else //原理是通过js代码增加/删除标签
2) v-show //原理是通过css样式改变标签状态
2
3
# 1.6.2. 比较v-if与v-show
如果需要频繁切换 v-show 较好
当条件不成立时, v-if的所有子节点不会解析(项目中使用)
# 1.6.3. 代码实例
//v-if和v-else
<p v-if="ok">成功</p>
<p v-else>失败</p>
data:{
ok:true
}
//v-show
<p v-show="ok">成功</p>
<p v-show="!ok">失败</p>
<button @click="toggle">切换</button>
-----------------------------
data:{
ok:true
},
methods:{
toggle(){
this.ok=!this.ok
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 1.7. 列表渲染
列表显示指令
数组: v-for / index
对象: v-for / key
列表的更新显示
删除item
替换item
列表的高级处理
列表过滤
列表排序
# 1.7.2. 列表显示代码实例
<ul>
<li v-for="(item,index) in persons"> //item是遍历的每一项,index是下标,persons是数组名
{{item.id}}--{{item.name}}
</li>
</ul>
data: {
persons: [
{id: 1, name: "zhangsan1"},
{id: 2, name: "zhangsan2"},
{id: 3, name: "zhangsan3"}
]
}
2
3
4
5
6
7
8
9
10
11
12
# 1.7.3. 列表更新显示代码
<ul>
<li v-for="(item,index) in persons">
{{item.id}}--{{item.name}}
---
<button @click="deletep(index)">删除</button>
---
<button @click="updatap(index,{id:Date.now(),name:'zhangsan4'})">更新</button>
</li>
</ul>
-----------------------------------
data: {
persons: [
{id: 1, name: "zhangsan1"},
{id: 2, name: "zhangsan2"},
{id: 3, name: "zhangsan3"}
]
},
methods: {
// 删除
deletep(index){
this.persons.splice(index,1)
},
//更新
updatap(index,newp){
this.persons.splice(index,1,newp)
}
}
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
# 1.7.4 列表过滤排序代码
<input type="text" v-model="searchName">
<ul>
<li v-for="(p, index) in filterPersons" :key="p.id">
{{p.id}}--{{p.name}}--{{p.age}}
</li>
</ul>
<button @click="sortType=2">按年龄升序</button>
<button @click="sortType=3">按年龄降序</button>
<button @click="sortType=1">原本顺序</button>
---------------------------------------------
data: {
searchName: '',
sortType: 1, // 排序的类型, 1: 不排序, 2: 升序, 3: 降序
persons: [
{id: 1, name: 'Tom', age: 15},
{id: 2, name: 'Jack', age: 12},
{id: 4, name: 'Bob', age: 17},
{id: 6, name: 'Rose', age: 16},
{id: 8, name: 'Else', age: 13}
]
},
computed: {
filterPersons () {
// 1. 得到依赖数据
const {sortType, searchName, persons} = this
// 2. 进行计算处理, 产生结果数据并返回
// 过滤
const arr = persons.filter(p => p.name.indexOf(searchName)>=0)
// 可能需要排序,设置标识符
if (sortType!==1) {
arr.sort((p1, p2) => {
if (sortType===2) { // 升序
return p1.age - p2.age
} else { // 降序
return p2.age - p1.age
}
})
}
return arr
}
}
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
# 1.8. 事件处理
# 1.8.1. 绑定监听:
v-on:click="xxx" //简写 @click="xxx"
@click="test('hello', $event)"
//test-事件名
//hello-自己传的参数(可选)
//$event-事件默认参数(可选)
2
3
4
5
6
代码实例
<button @click="test('hello',$event)">test</button> //参数可以不传
data: {
msg:""
},
methods:{
test(msg,event){
console.log(msg,event.target.innerText)
}
}
2
3
4
5
6
7
8
9
# 1.8.2. 事件修饰符
.prevent : 阻止事件的默认行为 //event.preventDefault()---原生写法
.stop : 停止事件冒泡 // event.stopPropagation()---原生写法
代码实例
//阻止默认行为
<a href="http://www.baidu.com" @click.preven>百度</a>
//阻止事件冒泡
<div @click="test1">
<div @click.stop></div> //需要绑定到父元素上
</div>
2
3
4
5
6
# 1.8.3. 按键修饰符
.keycode : 操作的是某个keycode值的键
.keyName : 操作的某个按键名的键(少部分)
代码实例
<input type="text" v-model="msg" @keyup.13="test"> //keycoe值
<input type="text" v-model="msg" @keyup.enter="test"> //ketname值
data: {
msg:""
},
methods:{
test1(){
alert(this.msg)
}
}
2
3
4
5
6
7
8
9
10
# 1.9. 表单输入绑定
# 1.9.2. 使用v-model对表单数据自动收集
text/textarea
checkbox
radio
select
# 1.9.3. 代码实例
<form action="/xxx" @submit.prevent="register"> //阻止默认提交表单
<span>用户名: </span>
<input type="text" v-model="user.username"><br>
<span>密码: </span>
<input type="password" v-model="user.pwd"><br>
<span>性别: </span>
//使用value和data中的数据对应
<input type="radio" id="female" v-model="user.sex" value="女">
<label for="female">女</label>
<input type="radio" id="male" v-model="user.sex" value="男">
<label for="male">男</label><br>
<span>爱好: </span>
//使用value和data中的数据对应
<input type="checkbox" id="basket" v-model="user.likes" value="basket">
<label for="basket">篮球</label>
<input type="checkbox" id="foot" v-model="user.likes" value="foot">
<label for="foot">足球</label>
<input type="checkbox" id="pingpang" v-model="user.likes" value="pingpang">
<label for="pingpang">乒乓</label><br>
<span>城市: </span>
<select v-model="user.cityId">
<option value="">未选择</option>
//:value实时监听 :key指定唯一的值
<option v-for="(city, index) in allCitys" :key="city.id" :value="city.id">{{city.name}}</option>
</select><br>
<span>介绍: </span>
<textarea rows="10" v-model="user.info"></textarea><br><br>
<input type="submit" value="注册">
</form>
---------------------------------------------
data: {
user: { //user包裹对象
username: 'admin',
pwd: '',
sex: '女',
likes: ['foot'],
cityId: '2',
info: '',
},
allCitys: [
{id: 1, name: 'BJ'},
{id: 2, name: 'SH'},
{id: 3, name: 'SZ'},
]
},
methods:{
register () {
alert(JSON.stringify(this.user))
}
}
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
# 1.9.4 v-model修饰符
1.lazy //失去焦点或者回车时更新数据
2.number //让输入的内容自动转换为数字类型
3.trim //过滤左右两边空格
2
3
# 1.9.5代码实例
<input type="text" v-model.lazy="message">{{message}} //lazy
<input type="number" v-model.number="message">{{message}}//number
<input type="text" v-model.trim="message">{{message}} //trim
----------------------------------------------------
new Vue({
el: "#app",
data: {
message: "hello"
},
})
2
3
4
5
6
7
8
9
10
# 1.10. Vue实例生命周期
# 1.10.1. 生命周期流程图
# 1.10.2 . vue生命周期分析
//Vue中的this指向Vue的实例对象vm,所有操作指的是界面的操作
1. vue对象的生命周期
1). 初始化显示
beforeCreate()
--------------实现数据代理: 后面可以通过vm读取data中的数据
created()
beforeMount()
--------------渲染界面
mounted()
2). 更新状态
beforeUpdate()
--------------更新界面
updated()
3). 销毁vue实例: vm.$destory()
beforeDestory()
--------------销毁数据
destoryed()
2. 常用的生命周期方法
mounted(): 发送ajax请求, 启动定时器等异步任务
beforeDestory(): 做收尾工作, 如: 清除定时器
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 1.11. 过渡&动画
# 1.11.1. 过渡
/* 显示的过渡样式 */
.yyy-enter-active {
transition: all 1s;
}
/* 隐藏的过渡样式 */
.yyy-leave-active {
transition: all 5s;
}
/* 隐藏时的样式 */
.yyy-enter, .yyy-leave-to {
opacity: 0;
transform: translateX(20px);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
实例代码
<style>
/* 显示的过渡样式 */
.yyy-enter-active {
transition: all 1s;
}
/* 隐藏的过渡样式 */
.yyy-leave-active {
transition: all 5s;
}
/* 隐藏时的样式 */
.yyy-enter, .yyy-leave-to {
opacity: 0;
transform: translateX(20px);
}
</style>
---------------------------------------
<button @click="ok">Toggle</button>
<transition name="yyy">
<p v-show="show">hello</p>
</transition>
---------------------------------------
data: {
show: true
},
methods:{
ok(){
this.show=!this.show
}
}
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
# 1.11.2. 动画
/* 显示动画样式 */
.xxx-enter-active {
animation: bounce-in .5s;
}
/* 隐藏动画样式 */
.xxx-leave-active {
animation: bounce-in .5s reverse;
}
/* 关键帧 */
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
实例代码
/* 显示动画样式 */
.xxx-enter-active {
animation: bounce-in .5s;
}
/* 隐藏动画样式 */
.xxx-leave-active {
animation: bounce-in .5s reverse;
}
/* 关键帧 */
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
------------------------------------------------
<button @click="ok">Toggle show</button>
<transition name="xxx">
<p v-if="show" style="display: inline-block;">Lorem</p>
</transition>
-------------------------------------------------
data: {
show: true
}
methods:{
ok(){
this.show=!this.show
}
}
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
# 1.12. 过滤器
# 1.12.1. 理解过滤器
功能: 对要显示的数据进行特定格式化后再显示
注意: 并没有改变原本的数据, 只是产生新的对应的数据
# 1.12.2. 全局过滤器
1.定义过滤器
Vue.filter("filterTime", (value,formatStr) => {
//value(必选)---被处理的数据,formatStr(可选)---自定义显示样式
return moment(value).format(formatStr || 'YYYY-MM-DD HH:mm:ss') //定义默认的显示样式
})
2.使用过滤器
<p>{{currentTime | filterTime("YYYY-MM-DD")}}</p> //自己定义的显示样式
<p>{{currentTime | filterTime("HH:mm:ss")}}</p>
2
3
4
5
6
7
8
# 1.12.3. 代码实例
<p>{{currentTime | filterTime("YYYY-MM-DD")}}</p>
<p>{{currentTime | filterTime("HH:mm:ss")}}</p>
----------------------------------------------
//引入第三方格式化时间库moment
<script src="https://cdn.bootcss.com/moment.js/2.24.0/moment.js"></script>
Vue.filter("filterTime", (value,formatStr) => {
return moment(value).format(formatStr || 'YYYY-MM-DD HH:mm:ss')
})
new Vue({
el: "#app",
data: {
currentTime:Date.now()
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1.12.4. 局部过滤器
//注册局部过滤器
<div id="app">{{price | showPrice }}</div>
------------------------------------------
new Vue({
el: "#app",
data: {
price: 55
},
filters:{
showPrice(price){
return "¥"+price.toFixed(2)
}
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1.13. 内置指令与自定义指令
# 1.13.1. 常用内置指令
v-text : 更新元素的 textContent
v-html : 更新元素的 innerHTML
v-if : 如果为true, 当前标签才会输出到页面
v-else: 如果为false, 当前标签才会输出到页面
v-show : 通过控制display样式来控制显示/隐藏
v-for : 遍历数组/对象
v-on : 绑定事件监听, 一般简写为@
v-bind : 强制绑定解析表达式, 可以省略v-bind
v-model : 双向数据绑定
ref : 指定唯一标识, vue对象通过$refs属性访问这个元素对象
v-cloak : 防止闪现, 与css配合: [v-cloak] { display: none }
# 1.13.2. 自定义指令
1) 注册全局指令
Vue.directive('my-directive', function(el, binding){
//my-directive---指令名,el---指令属性所在的标签元素对象(直接用),binding---包含指令相关信息数据的对象
el.innerHTML = binding.value.toupperCase()
})
-----------------------
2) 注册局部指令
directives : {
'my-directive' : function (el, binding) {
el.innerHTML = binding.value.toupperCase()
}
}
-----------------------
3) 使用指令
v-my-directive='xxx'
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 1.13.3. 代码实例
<p v-upper-text="msg"></p>
---------------------------
//定义全局(全局生效)
Vue.directive('upper-text', function (el, binding) {
el.innerText = binding.value.toUpperCase()
})
new Vue({
el: "#app",
data: {
msg:"hello"
},
//定义局部,只在当前Vue生效
directives:{
"upper-text"(el, binding){
el.innerText = binding.value.toUpperCase()
}
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 1.14. 自定义插件
# 1.14.1. 实例代码
插件JS
(function (window) {
// 定义插件对象
const MyPlugin = {}
// 所有的插件对象都必须有一个install方法
MyPlugin.install = function (Vue, options) {
console.log('MyPlugin.install()')
// 1. 添加全局方法或属性
Vue.myGlobalMethod = function () {
console.log('Vue.myGlobalMethod()')
}
// 2. 添加一个全局资源(asset)
Vue.directive('my-directive',(el, binding) => {
el.innerText = binding.value + '--------'
})
// 4. 添加一个实例方法
Vue.prototype.$myMethod = function () {
console.log('vm $myMethod()')
}
}
// 暴露插件对象
window.MyPlugin = MyPlugin
})(window)
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
页面使用插件
// 声明使用Vue插件
Vue.use(MyPlugin) // 内部调用插件的install方法来安装插件
Vue.myGlobalMethod()
const vm = new Vue({
el: '#test',
data() {
return {
msg: 'atguigu.com'
}
},
})
vm.$myMethod()
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 第2章:vue组件化编码
# 2.1. 使用vue-cli创建模板项目
# 2.1.1. 说明
vue-cli是vue官方提供的脚手架工具
github: https://github.com/vuejs/vue-cli
作用: 从https://github.com/vuejs-templates下载模板项目
# 2.1.2. 创建vue项目
//1.vue-cli3.xx版本
npm install -g @vue/cli //安装vue/cli
vue create vue-demo //创建项目,vue-demo项目名
//2.vue-cli2.xx版本
npm install -g @vue/cli-init //安装vue/cli
vue init webpack vue-demo //创建项目,vue-demo项目名
npm run dev //运行项目
npm run build //打包项目
2
3
4
5
6
7
8
9
10
11
12
# 2.1.3. 模板项目的结构(vue2.xxx)
|-- build : webpack相关的配置文件夹(基本不需要修改)
|-- dev-server.js : 通过express启动后台服务器
|-- config: webpack相关的配置文件夹(基本不需要修改)
|-- index.js: 指定的后台服务的端口号和静态资源文件夹
|-- node_modules
|-- src : 源码文件夹
|-- components: vue组件及其相关资源文件夹
|-- App.vue: 应用根主组件
|-- main.js: 应用入口js
|-- static: 静态资源文件夹
|-- .babelrc: babel的配置文件
|-- .eslintignore: eslint检查忽略的配置
|-- .eslintrc.js: eslint检查的配置
|-- .gitignore: git版本管制忽略的配置
|-- index.html: 主页面文件
|-- package.json: 应用包配置文件
|-- README.md: 应用描述说明的readme文件
# 2.2. 项目的打包与发布
# 2.2.1. 打包:
npm run build
# 2.2.2. 发布使用静态服务器工具包
npm install -g serve
serve dist
访问: http://localhost:5000
# 2.3. 组件定义与使用
# 2.3.1. vue文件的组成(3个部分)
<template>
页面模板
</template>
<script>
export default {
data() {
return {}
},
methods: {},
computed: {},
components: {}
}
</script>
3)样式
<style>
样式定义
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 2.3.2. 基本使用
1.创建组件
2.注册标签
3.使用组件
2
3
创建组件home
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'Home',
data () {
return {
msg: '我是home组件'
}
}
}
</script>
<style scoped>
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
在App中使用home
<template>
<div id="app">
<Home/> //3.使用组件
</div>
</template>
<script>
//1.引入home组件
import Home from './components/home'
export default {
name: 'App',
components: {
Home //2.注册标签
}
}
</script>
<style>
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 2.4. 组件间通信
# 2.4.1. 组件间通信基本原则
不要在子组件中直接修改父组件的状态数据
数据在哪, 更新数据的行为(函数)就应该定义在哪
# 2.4.2. vue组件间通信方式
props(父传子) $emit(子传父)
消息订阅与发布(如: pubsub库) / 事件总线
slot
vuex
# 2.5. 组件间通信1: props $emit
# 2.5.1. 父传子
App.vue
<template>
<div id="app">
<Home :cmessage="message"></Home>
</div>
</template>
<script>
import Home from './components/home'
export default {
name: 'App',
data(){
return{
message:"foo"
}
},
components: {
Home
}
}
</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
home.vue
<template>
<div>
<h1>{{cmessage}}</h1>
</div>
</template>
<script>
export default {
name: 'Home',
props:{
cmessage:{ //接收父组件传递的数据
type:String, //指定类型
required:true,//必须传
default:"bar"//默认值
},
cbooks:{
type: Array,
default(){ //当传递默认值的是数组或者对象时,必须是函数的形式
return []
},
required: true
}
}
}
</script>
<style scoped>
</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
# 2.5.2 子传父
home.vue
<template>
<div>
<button @click="btnClcik">子传父</button>
</div>
</template>
<script>
export default {
name: 'Home',
data(){
return{
count:0
}
},
methods:{
btnClcik(){
this.$emit("change",this.count) //通过$emit()传递数据,change是事件名
}
}
}
</script>
<style scoped>
</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
App.vue
<template>
<div id="app">
<Home @change="fchange"></Home> //通过v-on接收数据,默认带着传过来的数据
</div>
</template>
<script>
import Home from './components/home'
export default {
name: 'App',
components: {
Home
},
methods:{
fchange(value){ //value是传递过来的参数
console.log(value)
}
}
}
</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
# 2.6组件间的访问
1.父组件访问子组件:通过$children(不常用)或者$refs(常用)
2.子组件访问父组件:通过$parent(不常用)
3.访问根组件:通过$root
2
3
# 2.6.1父访问子
App.vue
<template>
<div id="app">
<Home ref="aaa"></Home> //通过ref为子组件绑定标识
<Button @click="btnclick">ref访问</Button>
</div>
</template>
<script>
import Home from './components/home'
export default {
name: 'App',
data(){
return{
message:"foo"
}
},
components: {
Home
},
methods:{
btnclick(){
console.log(this.$refs.aaa.count) //通过$refs获取子组件的内容
}
}
}
</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
home.vue
<template>
<div>
</div>
</template>
<script>
export default {
name: 'Home',
data(){
return{
count:0
}
}
}
</script>
<style scoped>
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2.7. 组件间通信3: 消息订阅与发布(pubsub-js库)
# 2.7.1. 订阅消息
PubSub.subscribe('msg', function(msg, data){})
# 2.7.2. 发布消息
PubSub.publish('msg', data)
# 2.7.3. 注意
优点: 此方式可实现任意关系组件间通信(数据)
# 2.7.4. 事件的2个重要操作(总结)
绑定事件监听 (订阅消息)
目标: 标签元素
事件名(类型): click/focus
回调函数: function(event){}
触发事件 (发布消息)
DOM事件: 用户在浏览器上对应的界面上做对应的操作
自定义: 编码手动触发
# 2.8. 组件间通信4: slot
# 2.8.1. 理解
此方式用于父组件向子组件传递标签数据
# 2.8.2. 子组件: home.vue
<template>
<div>
<slot></slot> //默认插槽
<slot name="center"></slot> //具名插槽
<slot name="right" :data="message"></slot> //作用域插槽
</div>
</template>
<script>
export default {
name: 'Home',
data(){
return{
message:"hello"
}
}
}
</script>
<style scoped>
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 2.8.3. 父组件: App.vue
<template>
<div id="app">
<Home>
//1.默认插槽
<div>默认插槽</div>
//2.具名插槽
<template slot="center">
<div>具名插槽</div>
</template>
//3.作用域插槽,用test接收,data为访问的数据
<template #right="test"> //v-slot="center"可以简写为#center
<div>{{test.data}}</div>
</template>
</Home>
<!-- <div slot="center"></div>-->
</div>
</template>
<script>
import Home from './components/home'
export default {
name: 'App',
data(){
return{
message:"foo"
}
},
components: {
Home
}
}
</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
# 2.9 组件中的资源引入
# 2.9.1引入css
//在其他组件中引入
<style>
@import "./assets/css/base.css";
</style>
2
3
4
5
# 2.9.2文件路径---起别名
https://blog.csdn.net/asfcyg/article/details/106224090
# 第3章:vue-ajax
# 3.1. axios的使用
# 3.1.1. 在线文档
https://github.com/pagekit/vue-resource/blob/develop/docs/http.md
# 3.1.2. 下载:
npm install axios --save
# 3.1.3 axios的封装
network/request.js
import axios from "axios"; //引入axios
//第一步
export function request(config) { //创建axios实例并暴露
const instance=axios.create({
baseURL:"http://123.207.32.32:8000/",
timeout:5000
})
//第二步
//请求拦截器
instance.interceptors.request.use(
(config) => {
console.log(config) //在请求直接做的事情
return config //必须return出去
},
(error) => {
// console.log()
}
)
//响应拦截器
instance.interceptors.response.use(
(value) => {
console.log(value)
return value
},
(error) => {
// console.log(error)
}
)
//第三步
return instance(config) //返回一个promise的实例
}
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
组件中调用
import {request} from "./network/request"; //引入封装好的axios
request({ //调用requset
url:"/home/multidata"
})
.then((value) => {
console.log(value)
})
.catch((reason) => {
console.log(reason)
})
2
3
4
5
6
7
8
9
10
11
12
# 第4章:vue UI组件库
# 4.1. 常用
Mint UI:
a. 主页: http://mint-ui.github.io/#!/zh-cn
b. 说明: 饿了么开源的基于vue的移动端UI组件库
Element
a. 主页: http://element-cn.eleme.io/#/zh-CN
b. 说明: 饿了么开源的基于vue的PC端UI组件库
# 4.2. 使用Element UI
1.下载
npm i element-ui -S
2、在 main.js
中配置 element 组件库
import ElementUI from 'element-ui' //引入ElementUI
import 'element-ui/lib/theme-chalk/index.css' //全局引入css
Vue.use(ElementUI); //注册ElementUI
2
3
3.组件中使用
参考文档 http://element-cn.eleme.io/#/zh-CN
# 第5章:vue-router
# 5.1. 理解
# 5.1.1. 说明
官方提供的用来实现SPA的vue插件
github: https://github.com/vuejs/vue-router
中文文档: http://router.vuejs.org/zh-cn/
下载: npm install vue-router --save
# 5.2. 基本路由的使用
# 5.2.1配置路由
1.导入路由,调用Vue.use()
2.创建路由实例,传入路由映射配置
3.在Vue实例中挂载路由实例
2
3
# 5.2.2. 使用路由
1.创建路由组件
2.配置路由映射
3.使用路由 <router-link></router-link> <router-view/>
2
3
# 5.2.3.代码实例
router/index.js
import Router from 'vue-router'
Vue.use(Router) //1.导入路由,调用Vue.use()
//2.创建路由实例,传入路由映射配置
export default new Router({
routes: [
{
path: '/home',
component: Home
},
{
path: "/about",
component: About
}
]
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
src/main.js
import router from './router'
new Vue({
el: '#app',
router, //3.在Vue实例中挂载路由实例
render: h => h(App)
})
2
3
4
5
6
1.创建路由组件
components/home,components/about
<template>
<div>
home
</div>
</template>
<script>
export default {
name: "Home"
}
</script>
<style scoped>
</style>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
router/index.js
import Home from "../components/home"
import About from "../components/about"
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
//2.配置路由映射
routes: [
{
path: '/home',
component: Home
},
{
path: "/about",
component: About
}
]
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Vue.app 3.使用路由
<template>
<div id="app">
<router-link to="/home">home</router-link> //路由链接
<router-link to="/about">about</router-link>
<router-view/> //用于渲染当前路由组件
</div>
</template>
2
3
4
5
6
7
# 5.2.4 重定向路由(默认路由)
router/index.js
routes: [
{
path: "",
redirect:"/home" //重定向到home
}
]
2
3
4
5
6
# 5.2.5 配置history
router/index.js
routes: [],
mode:"history" //配置history,默认地址栏中为hash,有#号
2
# 5.2.6. router-link其他属性
1.tag //渲染成什么组件
2.replace //不能回退
3.active-class //修改默认选中的class
4.linkActiveClass: 'active', // 指定选中的路由链接的class,需要在router中修改
2
3
4
App.vue
<template>
<div id="app">
//tag渲染标签 //replace不会回退 //active-class="active" 修改默认class
<router-link to="/home" tag="button" replace active-class="active">home</router-link>
<router-view/>
</div>
</template>
<style>
.active{
color: red;
}
</style>
2
3
4
5
6
7
8
9
10
11
12
13
router/index.js
routes: [],
mode:"history",
linkActiveClass:"active" //全局修改选中class
2
3
# 5.2.7其他路由跳转方式
$router.push()
$router.replace()
2
App.vue
<template>
<div id="app">
<button @click="clickHome">home</button>
<button @click="clickAbout">about</button>
<router-view/>
</div>
</template>
export default {
name: 'App',
methods:{
clickHome(){
this.$router.push("/home") //通过$router的方式实现跳转
},
clickAbout(){
this.$router.push("/about")
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 5.3动态路由
1.配置路由参数
2.在组件中使用
3.子组件拿到参数
2
3
router/index.js
routes: [
{
path: '/home/:id', //通过id来标识,任何值都可以
component: Home
}
],
2
3
4
5
6
App.vue
<router-link :to="'/home/'+userId">home</router-link> //显示到地址栏上,注意一定要使用v-bind
home.vue
<h1>{{userId}}</h1> //使用拿到的参数
-----------------
<script>
export default {
name: "Home",
data(){
return{
userId:this.$route.params.id //通过this.$route.params拿到参数
}
}
}
</script>
2
3
4
5
6
7
8
9
10
11
12
# 5.4路由懒加载
routes: [
{
path: "",
redirect:"/home"
},
{
path: '/home/:id',
component: () => import("../components/home") //懒加载,不用导入,直接引入
},
{
path: "/about",
component: () => import("../components/about")
}
],
2
3
4
5
6
7
8
9
10
11
12
13
14
# 5.5. 嵌套路由
# 5.3.1. 子路由组件
HomeNews.vue
HomeMessage.vue
# 5.3.2. 配置嵌套路由:
router/index.js
{
path: '/home',
component: () => import("../components/home"),
children:[ //配置子路由
{
path: "",
redirect:"news"
},
{
path:"news", //配置news路由,不需要加/
component:()=> import("../components/HomeNews")
},
{
path:"message",
component:()=> import("../components/HomeMessage")
}
]
},
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 5.3.3. 路由链接:
Home.vue
<template>
<div>
<router-link to="/home/news">news</router-link>
<router-link to="/home/message">message</router-link>
<router-view></router-view>
</div>
</template>
2
3
4
5
6
7
# 5.5. 向路由组件传递数据
# 5.4.1. 方式1: 路由路径携带参数(param/query)
router/index.js
{
path: '/home', //query传参普通配置
component: () => import("../components/home"),
}
2
3
4
App.vue
//以 :to="{path:'',query:{}}"形式传参
<router-link :to="{path:'/home',query:{name:'foo',age:18}}">home</router-link>
2
home.vue
this.$route.query //接收参数
# 5.4.2. 方式2:编程式传参
this.$router.push({
path:"/home",
query:{
name:"foo",
age:18
}
})
2
3
4
5
6
7
# 5.6. keep-alive(缓存)
# 5.6.1. 理解
默认情况下, 被切换的路由组件对象会死亡释放, 再次回来时是重新创建的
如果可以缓存路由组件对象, 可以提高用户体验
# 5.6.2. 编码实现
<keep-alive>
<router-view></router-view>
</keep-alive>
2
3
# 5.7. 路由守卫
vue中路由守卫一共有三种,一个全局路由守卫,一个是组件内路由守卫,一个是router独享守卫
全局路由守卫
router.beforeEach((to, from, next) => {})
//to: Route: 即将要进入的目标 路由对象
//from: Route: 当前导航正要离开的路由
//next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
router.afterEach(to,from) = {}
2
3
4
5
组件内路由守卫
beforeRouteEnter (to, from, next) {
// 注意,在路由进入之前,组件实例还未渲染,所以无法获取this实例,只能通过vm来访问组件实例
next(vm => {})
}
beforeRouteUpdate (to, from, next) {
// 同一页面,刷新不同数据时调用,
}
beforeRouteLeave (to, from, next) {
// 离开当前路由页面时调用
}
2
3
4
5
6
7
8
9
10
router独享守卫
export default new VueRouter({
routes: [
{
path: '/',
name: 'home',
component: 'Home',
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
2
3
4
5
6
7
8
9
10
11
12
#
# 第6章:vuex
# 6.1. vuex理解
# 6.1.1. vuex是什么
github站点: https://github.com/vuejs/vuex
在线文档: https://vuex.vuejs.org/zh-cn/
简单来说: 对vue应用中多个组件的共享状态进行集中式的管理(读/写)
# 6.1.2. 状态自管理应用
state: 驱动应用的数据源
view: 以声明方式将state映射到视图
actions: 响应在view上的用户输入导致的状态变化(包含n个更新状态的方法)
# 6.2 vuex的基本使用
# 6.2.1 安装
1.npm install vuex --save //安装vuex
# 6.2.2 创建
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
// 1.挂载Vuex
Vue.use(Vuex)
// 2.创建Vuex并暴露
export default new Vuex.Store({
state:{
//存放状态的
},
mutations:{
//修改同步状态
},
actions:{
//修改异步状态
},
getters:{
//加工state,相当于组件中的computed
},
modules:{
}
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 6.2.3 挂载Vue实例
main.js
import Vue from 'vue'
import store from './store'
new Vue({
el: '#app',
store, //挂载
components: { App },
template: '<App/>'
})
2
3
4
5
6
7
8
9
10
# 6.2.4 state
router/index.js
state:{
count:0 //保存状态
},
2
3
home.vue
<h1>{{$store.state.count}}</h1> //获取状态
# 6.2.5 mutations
router/index.js
mutations:{
increment(state){
state.count++ //更新同步状态
},
addbooks(state,books){
console.log(books) //传递参数
}
},
2
3
4
5
6
7
8
home.vue
methods:{
add(){
this.$store.commit("increment") //获取同步状态,increment对应mutations中的方法
},
addBooks(){
const books={name:"Java",price:100}
this.$store.commit("addbooks",books) //获取参数
}
}
2
3
4
5
6
7
8
9
# 6.2.6 增删state中的成员
在Mutations的方法中,应当使用Vue提供的方法来进行操作。如果使用在state中没有初始化,则Vue不能对数据进行实时响应。
Vue.set 为某个对象设置成员的值,若不存在则新增
Vue.set(state,"name","foo")
Vue.delete 删除成员
Vue.delete(state,'name')
# 6.2.7 getters
router/index.js
getters:{
sum(state){ //state状态
return state.count*3 //加工state
},
addsum(state,getters){ //state为当前VueX对象中的状态对象
//getters为当前getters对象,用于将getters下的其他getter拿来用
return getters.sum+state.count+5
}
},
2
3
4
5
6
7
8
9
home.vue
<h1>{{$store.getters.sum}}</h1> //获取加工后的状态
<h1>{{$store.getters.addsum}}</h1>
2
# 6.2.8 Actions
由于直接在mutation
方法中进行异步操作,将会引起数据失效。所以提供了Actions来专门进行异步操作,最终提交mutation
方法。
Actions中的方法有两个默认参数
context 上下文(相当于箭头函数中的this)对象
payload 挂载参数
操作流程
组件通过$store.dispatch()方法调用actions中的方法,actions通过context.commit()调用mutations中的方法来实现异步操作
2
3
4
5
router/index.js
actions:{
aEdit(context,payload){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
context.commit('edit',payload)
resolve()
},2000)
})
}
},
mutations:{
edit(state){
state.info.name='bar'
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
home.vue
this.$store.dispatch("aupdata")
# 6.2.9 Models
# 2.2.9.1 基本使用
当项目庞大,状态非常多时,可以采用模块化管理模式。Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter
、甚至是嵌套子模块——从上至下进行同样方式的分割。
models:{
a:{
state:{},
getters:{},
....
}
}
2
3
4
5
6
7
组件调用状态
this.$store.state.a
commit和dispatch方法和原来的一样
this.$store.commit('editKey')
this.$store.dispatch('aEditKey')
2
# 2.2.9.2 模块的细节
模块中mutations
和getters
中的方法接受的第一个参数是自身局部模块内部的state
models:{
a:{
state:{key:5},
mutations:{
Eidt(state){
console.log(state)
}
},
....
}
}
2
3
4
5
6
7
8
9
10
11
getters
中方法的第三个参数是根节点状态
getters:{
Eidt(state,getter,rootState){
return rootState.key + state.key
}
},
2
3
4
5
actions中方法获取局部模块状态是
context.state,根节点状态是
context.rootState
actions:{
Eidt(context){
console.log(context.state)
console.log(context.rootState)
}
}
},
2
3
4
5
6
7
# 6.2.10 规范目录结构
store:.
│ actions.js
│ getters.js
│ index.js
│ mutations.js
│ mutations_type.js ##该项为存放mutaions方法常量的文件,按需要可加入
│
└─modules
car.js
profile.js
2
3
4
5
6
7
8
9
10
index.js
import mutations from "./mutations";
export default new Vuex.Store({
state:{
info: {name:'foo',age:18}
},
mutations,
actions,
getters,
modules
})
2
3
4
5
6
7
8
9
10
11
mutations.js
export default {
updata(state){
state.info.name='bar'
}
}
2
3
4
5