vue2学习笔记

学习资源

Vue起步

HelloWorld

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello</title>

<!-- 使用script引入vue js库 -->
<script src="./vue.js"></script>
</head>

<body>
<div id="app">
// {{ }}插值表达式
{{ content }}
</div>

<script>
// 创建vue实例,el与id标签绑定,实例中声明data对象
// 使用vue实例访问data对象。
// 数据content {{ }}插值表达式 来更新ui
var app = new Vue({
el: '#app',
data: {
content:'hello world'
}
})
setTimeout(function(){
app.$data.content = 'bye world';
},2000)
</script>
</body>
</html>

mvvm 讲解

todolist-1
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>todolist</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">

<!--v-model指令 数据与UI双向绑定
1、app.$data.inputValue改变input值也会改变
2、input值改变 app.$data.inputValue 也会改变
-->
<input type="text" v-model="inputValue">

<!--v-on:click 或者 @click 绑定点击事件-->
<button @click="handleBtnClick">提交</button>

<ul>
<!-- v-for 循环列表指令
data中的 list 改变,ui也会改变(循环列表)
mvvm设计模式
-->
<li v-for="item in list">{{ item }}</li>
</ul>
</div>

<script>
var app = new Vue({
el:'#app',
data: {
inputValue:'',
list:[]
},
methods: {
handleBtnClick() {
// alert('click');
this.list.push(this.inputValue);
this.inputValue = '';
}
}
})
</script>
</body>
</html>

简单组件使用

todolist-2 全局注册组件
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>todolist全局组件</title>
<script src="./vue.js"></script>
</head>

<body>
<div id="app">

<!--v-model 双向绑定-->
<input type="text" v-model="inputValue">

<button @click="handleBtnClick">提交</button>

<ul>
<!---
1、子组件的使用
2、绑定子组件的属性
:content 或者 v-bind 子组件的属性绑定父组件的值
-->
<todo-item :content="item"
v-for="item in list">
</todo-item>
</ul>

</div>

<script>
// vue全局注册组件
// Vue.component 组件名字(驼峰命名),{}对象
Vue.component("TodoItem", {
//props属性对象,属性content接收父组件传来的值
//**父组件通过子组件的属性向子组件传值。
props: {
content:String,
},
template:"<li>{{ content }}</li>",
})

var app = new Vue({
el:'#app',
data: {
inputValue:'',
list:[]
},
methods: {
handleBtnClick() {
// alert('click');
this.list.push(this.inputValue);
this.inputValue = '';
}
}
})

/*
子组件定义使用
1、props 属性列表对象
2、template 模版
3、Vue.component 全局注册
4、父组件通过 :content 或者 v-bind 向子组件传值
*/

</script>
</body>
</html>

todolist-3 局部注册组件
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>todolist局部组件</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<!--v-model 双向绑定-->
<input type="text" v-model="inputValue">
<button @click="handleBtnClick">提交</button>
<ul>
<!---驼峰命名子组件的使用 :content v-bind子组件的属性绑定父组件的值-->
<todo-item :content="item"
v-for="item in list">
</todo-item>
</ul>
</div>

<script>
//局部注册组件
var TodoItem = {
props:{
content:String,
},
template:"<li>{{ content }}</li>",
}

var app = new Vue({
el:'#app',
//注册组件
components:{
TodoItem:TodoItem
},
data: {
inputValue:'',
list:[]
},
methods: {
handleBtnClick() {
// alert('click');
this.list.push(this.inputValue);
this.inputValue = '';
}
}
})

/*
局部注册组件:
1、声明组件
var TodoItem = { props, template }
2、vue实例中注册组件
new Vue({
el:'#app',
//注册组件
components:{
TodoItem:TodoItem
},
data:{}
methods:{}
})
*/
</script>
</body>
</html>

todolist-4 局部注册组件,子组件点击事件,子组件向父组件传值
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>todolist子向父传值</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">

<!--v-model 双向绑定-->
<input type="text" v-model="inputValue">

<button @click="handleBtnClick">提交</button>

<ul>
<!-- :content 或者 v-bind: 子组件的属性绑定父组件的值-->
<!-- @delete 监听子组件传值 -->
<todo-item :content="item"
:index="index"
@delete="handleItemDelete"
v-for="(item,index) in list">
</todo-item>
</ul>
</div>

<script>
//局部注册组件
var TodoItem = {
props:{
content:String,
index:0,
},
template:"<li @click='handleItemClick'>{{ content }}</li>",
methods:{
handleItemClick() {
// 子组件向父组件发送数据
this.$emit("delete",this.index);
}
}
}

var app = new Vue({
el:'#app',
//局部注册组件
components:{
TodoItem:TodoItem
},
data: {
inputValue:'',
list:[]
},
methods: {
handleBtnClick() {
this.list.push(this.inputValue);
this.inputValue = '';
},
//父组件方法,处理子组件传过来的值
handleItemDelete(index){
this.list.splice(index,1)
}
}
})

/**

1、声明子组件
var TodoItem = {
props:[],
template:{},
methods: {
handleItemClick() {
// 子组件向父组件发送数据
this.$emit("delete",this.index);
}
}
}

2、父组件中注册子组件
var app = new Vue({
el:'#app',
//局部注册组件
components:{
TodoItem:TodoItem
},
data:{},
methods:{
handleItemDelete(index){
this.list.splice(index,1)
}
}
})

3、 父组件中使用子组件,@delete=并监听子组件传值
<todo-item :content="item"
:index="index"
@delete="handleItemDelete"
v-for="(item,index) in list">
</todo-item>

*/
</script>
</body>
</html>

总结

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1、script引入vue.js
2、全局注册组件
Vue.component 全局注册
3、局部注册组件
var app = new Vue({
el:'#app',
//局部注册组件
components:{
TodoItem:TodoItem
},
4、子父组件传值
父->子:父组件通过 :content 或者 v-bind 绑定子组件的属性向子组件传值。
子->父:子组件通过this.$emit("delete",this.index)向父组件发送数据,父组件通过@delete=监听子组件传值

5、v-bind:content 简写: :content

Vue基础

vue实例

  • 每一个组件都是一个vue实例
  • 每一个组件都有自己的属性和方法

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
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue生命周期</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
{{ message }}
</div>

<script>
// 生命周期函数是 vue实例在某个时间点自动执行的函数
var vm = new Vue({
el:'#app',
data:{
message:'hello world',
},
beforeCreate(){
console.log('beforeCreate');
},
//注入组件等
created(){
console.log('created');
},
//是否有el、template, 渲染之前
beforeMount(){
console.log('beforeMount');
console.log(this.$el); // <div id="app"> {{ message }}</div>
},
//渲染完成
mounted(){
console.log('mounted');
console.log(this.$el); // <div id="app"> hello world</div>
},
//调用 vm.$destroy() 会执行下面的方法
beforeDestroy(){
console.log('beforeDestroy');
},
destroyed(){
console.log('destoryed');
},
//当数据data 发生变化时调用
beforeUpdate(){
console.log('beforeUpdate');
},
updated(){
console.log('updated');
}
})
</script>
</body>
</html>

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
31
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模版语法</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<!-- 插值表达式 -->
<div>{{ name }}</div>

<!--v-text 引号里面是js表达式,表示innerText 与name绑定-->
<div v-text="name + ' Lee'"></div>

<!--v-html 引号里面是js表达式,表示innerHtml 与h1text绑定-->
<div v-html="h1text"></div>
</div>

<script>
var vm = new Vue({
el:'#app',
data:{
name:'dellwd',
h1text:'<h1>haha</h1>',
}
})
</script>
</body>
</html>

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
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue计算属性、方法、侦听器</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<!-- {{ fullName() }} -->
{{ fullName }}
{{ age }}
</div>

<script>
var vm = new Vue({
el:'#app',
data:{
firstName:'lee',
lastName:'mike',
age: 28,
fullName:'mike lee'
},
//计算属性:具有缓存的作用,性能好,当firstName或者lastName改变的时候才执行,如果没有改变则取缓存
// 测试 vm.age = 27 改变刷新页面时,计算属性没有变化
// 使用计算属性,有返回值时,直接作为属性使用
// computed:{
// fullName: function() {
// console.log('计算了一次')
// return this.firstName + ' ' + this.lastName
// }
// },
// 方法:不能缓存
// methods:{
// fullName() {
// console.log('计算了一次')
// return this.firstName + ' ' + this.lastName
// }
// },
//具有缓存作用,当firstName或者lastName改变的时候才执行
watch:{
firstName:function(){
console.log('计算了一次')
this.fullName = this.firstName + ' ' + this.lastName
},
lastName:function(){
console.log('计算了一次')
this.fullName = this.firstName + ' ' + this.lastName
}
}
})

// 如果效果一样,优选computed
</script>
</body>
</html>

Vue计算属性、get、set 方法设置获取属性

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue计算属性set、get</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
{{ fullName }}
</div>

<script>
var vm = new Vue({
el:'#app',
data:{
firstName:'lee',
lastName:'mike',
},
computed:{
//定义对象 fullName
fullName: {
//get 获取fullName值
get:function() {
return this.firstName + ' ' + this.lastName
},
//set 设置fullName 属性值,改变数据,vm.fullName = 'mike wang'
set:function(value) {
var arr = value.split(' ')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
})
</script>
</body>
</html>

样式绑定-1 class的对象绑定

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>样式绑定</title>
<script src="./vue.js"></script>
<style>
.activated {
color:red;
}
</style>
</head>
<body>
<div id="app">
<!-- class的对象绑定 -->
<div @click="handleDicClick"
:class="{activated:isActivated}">

hello world
</div>

<script>
var vm = new Vue({
el:'#app',
data: {
isActivated:false,
},
methods:{
handleDicClick() {
this.isActivated = !this.isActivated
}
}
})

/*
样式绑定 class的对象绑定
1、<div :class="{activated:isActivated}"> hello world </div>
数组绑定 activated 字符串是否为空判断
<div :class="[activated]"> hello world </div>
2、声明样式
<style>
.activated {
color:red;
}
</style>
*/
</script>
</div>
</body>
</html>

样式绑定-2 style的对象绑定

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>样式绑定3</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<!--style的对象绑定 :style=可以是对象也可以是数组-->
<div @click="handleDicClick"
:style="[styleObj,{fontSize:'20px'}]">
hello world
</div>

<script>
var vm = new Vue({
el:'#app',
data: {
styleObj:{
color:'black'
}
},
methods:{
handleDicClick() {
this.styleObj.color = this.styleObj.color === "black" ? "red" : "black"
}
}
})

/**
style对象绑定

<div @click="handleDicClick"
:style="[styleObj,{fontSize:'20px'}]">

data: {
styleObj:{
color:'black'
}
}

*/
</script>
</div>
</body>
</html>

样式绑定-3 class的数组绑定

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 lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>样式绑定</title>
<script src="./vue.js"></script>
<style>
.activated{
color:red;
}
</style>
</head>
<body>
<div id="app">
<!--class的数组绑定-->
<div @click="handleDicClick"
:class="[activated,activatedOne]">
hello world
</div>

<script>
var vm = new Vue({
el:'#app',
data: {
activated:"",
activatedOne:'activated-one',
},
methods:{
handleDicClick() {
this.activated = this.activated === "activated" ? "" : "activated"
}
}
})
</script>
</div>
</body>
</html>

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue条件渲染</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">

<!-- v-if 直接添加或者移除dom, 标签元素会被移除 -->
<!-- <div v-if="show">{{ content }}</div> -->

<!-- v-show 控制dom的显示隐藏效率高,标签会display:none,还会存在在dom上 -->
<!-- <div v-show="show">{{ content }}</div> -->

<!-- v-if v-else-if v-else 必须连接在一起使用,中间不能加标签 -->
<!--
<div v-if="test === 'a'">this is a</div>
<div v-else-if="test === 'b'">this is b</div>
<div v-else>this is others</div>
-->

<!-- key用于相同的标签,在虚拟dom中唯一存在,渲染时不会缓存, 适合唯一显示的元素 -->
<div v-if="show">
用户名:<input key="username"/>
</div>
<div v-else>
邮箱名:<input key="emailname"/>
</div>
</div>

<script>
var vm = new Vue({
el: '#app',
data: {
show:false,
test:'a',
content:'hello world'
}
})
// setTimeout(function(){
// vm.$data.content = 'bye world';
// },2000)
</script>
</body>
</html>

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
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vfor渲染</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<!-- 添加key唯一渲染 -->

<!--
如果操作list的下标元素赋值,页面不会刷新, 比如:this.list[4] = {id:'1001',name:'dell'};
只有遍历list或者改变list的引用页面才会刷新
遍历方法:push、pop、shift、unshift、splice、sort、reverse
比如:vm.list.splice(1,1,{}) 删除第1条,增加一条,会刷新页面

也可以通过set方法改变list
Vue.set(vm.list,下标,元素)
vm.$set(vm.list,下标,元素)
-->

<!--
<div v-for="(item,index) of list"
:key="item.id">
{{ item.name }} --- {{ index }}
</div>
-->

<!--
template只是包裹元素,不会渲染出来
-->
<template v-for="(item,index) of list"
:key="item.id">
<div>{{ item.name }} --- {{ index }}</div>
<span>{{ item.name }}</span>
</template>

<!--
对象循环,只有改变对象的引用才会刷新渲染
可以通过vue的set方法改变对象,添加属性等:
Vue.set(vm.userInfo,'address','beijing')
vm.$set(vm.userInfo,'address','beijing')
-->

<div v-for="(item,key,index) of userInfo">
{{ item }} --- {{ key }} --- {{ index }}
</div>
</div>

<script>
var vm = new Vue({
el: '#app',
data: {
content:'hello world',
list:[
{
id:'1001',
name:'dell'
},
{
id:'1002',
name:'piter'
},
{
id:'1003',
name:'chid'
},
],
userInfo:{
name:'lihao',
age:23,
sex:'woman',
salary:'secret'
}
}
})
</script>
</body>
</html>

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
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>事件绑定</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<button @click="handleBtnClick($event,1,2,3)">按钮</button>
<!--
1、绑定的事件参数中加 $event,事件方法中才能获取到event,除了$event,也可以添加其他参数
2、点击事件修饰符
@click.prevent="handleCile" 阻止事件
@click.self: e.target = e.currentTarget
只有点击的标签是当前标签才会执行。
@click.once: 事件只会执行一次
@click.capture: 捕获规则,事件由外向内传递
默认冒泡:事件由内向外传递
-->
<div @click.self="handleNiceClick">
nice 点击nice才会触发事件
<div>
hello world
</div>
</div>

<div @click.capture="handleOuter">
<div @click.capture="handleInner">
hello world2
</div>
</div>

<!-- 按键修饰符 -->
<input @keydown.enter="handleKeyDown"/>
</div>

<script>
var app = new Vue({
el: '#app',
data: {
content:'hello world'
},
methods:{
handleBtnClick(e,o,t,th){
console.log(e,o,t,th);
},
handleNiceClick(){
alert()
},
handleOuter(){
alert('Outer')
},
handleInner(){
alert('Inner')
},
handleKeyDown(e){
console.log(e.target.value)
}
}
})
</script>
</body>
</html>

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>表单绑定</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<!-- v-model 可以绑定在 areatext、radio、checkbox等上面 -->

<input v-model="value"/>
{{ value }}

<select v-model="value">
<option disabled>--请选择--</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>

<!-- lazy修饰符,焦点失去时赋值 -->
<input type="text" v-model.lazy="value2"/>
{{ value2 }}

<!-- number修饰符,为数字时赋值 -->
<!-- trim修饰符去除首尾空格 -->
<input type="text" v-model.number="value3"/>
{{ value3 }}
</div>

<script>
var app = new Vue({
el: '#app',
data: {
value:'',
value2:'',
value3:'',
content:'hello world'
},
watch:{
value3:function(){
console.log(typeof this.value3)
}
}
})
</script>
</body>
</html>

深入理解Vue组件

组件细节点1

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件细节</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<!--
1、组件is语法的使用
ul、ol、select标签写法注意
2、子组件中定义data必须是一个函数
-->
<table>
<tbody>
<tr is="row"></tr>
<tr is="row"></tr>
<tr is="row"></tr>
</tbody>
</table>
</div>

<script>
Vue.component('row',{
data:()=> {
return {
content:"this is a row",
}
},
template:'<tr><td>{{ content }}</td></tr>'
})

var app = new Vue({
el: '#app',
data: {
content:'hello world'
}
})
</script>
</body>
</html>

组件细节点2

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ref的使用</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<!--
1、子组件向父组件传值 父组件监听 @change
2、子组件 this.$emit('change')
-->

<!--
2、ref的使用,dom节点的引用
ref也可以获取子组件节点,然后获取子组件中的属性
<counter @change="handleChange" ref="one"></counter>
this.$refs.one.number
-->
<counter @change="handleChange" ref="one"></counter>
<counter @change="handleChange" ref="two"></counter>

<div>
{{ total }}
</div>
</div>

<script>
//计数组件
Vue.component('counter',{
data:function(){
return {
number: 0,
}
},
template:'<div @click="handleNumber">{{ number }}</div>',
methods: {
handleNumber() {
this.number ++
// 触发父组件的change监听,也可以发送数据给父组件
this.$emit('change')
}
}
})

var app = new Vue({
el: '#app',
data: {
content:'hello world',
total:0
},
methods:{
//子组件触发的事件调用这个方法
handleChange() {
this.total = this.$refs.one.number + this.$refs.two.number
}
}
})
</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
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>组件传值</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<!--
给子组件的属性count赋值,也就是父组件传过来的值
@inc 监听子组件触发的事件
-->
<counter :count="0" @inc="handelInc"></counter>
<counter :count="0" @inc="handelInc"></counter>

<div>{{ total }}</div>
</div>

<script>
//定义子组件
var counter = {
template:'<div @click="handleClick">{{ number }}</div>',
//定义属性接收父组件传来的值
props: {
count: 0
},
data: function(){
return {
//父组件传来的数据直接赋值给number
number:this.count,
}
},
methods:{
handleClick(){
//子组件中不能直接操作父组件的属性,因为有可能其他组件引用,改变其值
// this.count += 1

//可以定义data数据来操作
this.number += 1

//事件触发传递给父组件值
this.$emit('inc',1)
}
}
}

var app = new Vue({
el: '#app',
components:{
counter:counter
},
data: {
total:0
},
methods:{
handelInc(number){
this.total += number
}
}
})

/*
//1、子组件给父组件传值通过触发监听函数
//2、父组件给子组件传值通过给子组件属性赋值
//3、子组件中不能直接操作父组件的属性,因为有可能其他组件引用,改变其值,
可以定义data数据来操作,将接受过来的props属性赋值给data
*/
</script>
</body>
</html>

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
31
32
33
34
35
36
37
38
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<child content="hell"></child>
</div>

<script>
Vue.component('child',{
template:'<div>{{ content }}</div>',
props:{
content:{
type:[String,Number],
required:false,
default:'default value',
//数据校验
validator:function(value){
return (value.length > 5)
}
}
}
})

var app = new Vue({
el: '#app',
data: {
message:'hello world'
}
})
</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
36
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<!--
@click.native修饰符是组件在父组件的点击事件,子组件不会触发自己的点击事件
子组件触发父组件的点击事件
-->
<child @click.native="handleChildClick"></child>
</div>

<script>
Vue.component('child',{
template:'<div>hello child</div>',
})

var app = new Vue({
el: '#app',
data: {
content:'hello world'
},
methods:{
handleChildClick(){
alert('ddd')
}
}
})
</script>
</body>
</html>

bus 非父子组件传值

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>bus传值</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<child content='lee'></child>
<child content='dark'></child>
</div>

<script>
// 定义事件总线
// 在一个vue类上挂载了一个属性 bus,在所有的vue实例组件上都会有此属性bus
Vue.prototype.bus = new Vue()

Vue.component('child',{
template:'<div @click="handleClick">{{selfContent}}</div>',
props: {
content:String,
},
data:function() {
return {
selfContent:this.content
}
},
methods:{
handleClick() {
//bus发送数据
this.bus.$emit('change',this.selfContent)
}
},
// 生命周期钩子
mounted:function() {
//监听发来的数据
var this_ = this
this.bus.$on('change',function(msg){
this_.selfContent = msg
})
}
})

var app = new Vue({
el: '#app',
data: {
content:'hello world'
}
})

/*
1、在vue类上挂载属性bus
Vue.prototype.bus = new Vue()
2、bus发送事件
this.bus.$emit('change',this.selfContent)
3、bus接受事件
var this_ = this
this.bus.$on('change',function(msg){
this_.selfContent = msg
})

*/
</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
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 lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>插槽使用</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<body-content>
<div class="header" slot="header">header</div>
<div class="footer" slot="footer">footer</div>
</body-content>
</div>

<script>

Vue.component('body-content',{
template:`<div>
<slot name='header'></slot>
<div class='content'>content</div>
<slot name='footer'></slot>
</div>`
})

var app = new Vue({
el: '#app',
data: {
content:'hello world'
}
})

/*
1、插槽
在组件中插入一段dom元素,要插入的代码使用slot标签来包裹,等待传入dom元素
eg:
父组件中:
<child>
<h1>dell</h1>
</child>

子组件中:
template:
<div>
<p>hello</p>
<slot>默认内容</slot>
</div>

2、具名插槽:
给插槽定义名字,避免混乱
子组件中:
<slot name='header'></slot>
父组件中:
<div class="header" slot="header">header</div>
*/
</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
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 lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue作用域插槽</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<child>
<!--
子组件的值传递给了父组件
-->
<template slot-scope="props">
<!-- <li>{{ props.item }}</li> -->
<h3>{{ props.item }}</h3>
</template>
</child>
</div>

<script>
Vue.component('child',{
data:function(){
return {
list:[1,2,3,4],
}
},
template:`
<div>
<ul>
<slot v-for="item of list" :item=item />
</ul>
</div>
`,
})

var app = new Vue({
el: '#app',
data: {
content:'hello world'
}
})

/*
1、作用域插槽
用 template 定义
<template slot-scope="props"></template>
slot-scope="props" 接受插槽传递的数据
<h3>{{ props.item }}</h3> 使用数据
2、子组件定义插槽
<ul>
<slot v-for="item of list" :item=item />
</ul>
3、当子组件中不知道渲染什么样的dom时,使用作用域插槽
*/
</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
36
37
38
39
40
41
42
43
44
45
46
47
48
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>动态组件与v-once</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="app">
<!-- 动态组件 -->
<component :is="type"></component>
<button @click="handle">点击切换组件</button>
</div>

<script>
Vue.component('child-one',{
template:'<div>child-one</div>',
})

Vue.component('child-two',{
template:'<div>child-two</div>',
})

var app = new Vue({
el: '#app',
data: {
type:'child-one',
},
methods:{
handle(){
this.type = (this.type === 'child-one' ? 'child-two':'child-one')
}
}
})

/*
component 自带标签

动态切换组件
:is="type">
根据type的组件名字来切换

<div v-once> 只渲染一次
*/
</script>
</body>
</html>

vue动画特效

vue css动画

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>css动画</title>
<script src="./vue.js"></script>

<style>
.v-enter,
.v-leave-to {
opacity:0;
}
.v-enter-active,
.v-leave-active {
transition: opacity 1s;
}
</style>
</head>
<body>
<div id="app">

<transition>
<div v-show="show">
hello world
</div>
</transition>

<button @click="handleShow">点击我</button>
</div>

<script>
var app = new Vue({
el: '#app',
data: {
show:true,
},
methods:{
handleShow(){
this.show = !this.show
}
}
})

/*
transition 过渡的动画标签,包裹的标签会自动生成如下样式:
样式前缀默认为 v
.v-enter,
.v-leave-to

.v-enter-active,
.v-leave-active
*/
</script>
</body>
</html>

animate css 动画使用

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>animate css 使用</title>

<script src="./vue.js"></script>

<link rel="stylesheet" type="text/css" href="./animate.min.css"/>
</head>
<body>
<div id="app">
<!-- transition必须配置name 官网https://animate.style/ -->
<transition
name="animate__animated animate__bounce"
enter-active-class="animate__fadeIn"
leave-active-class="animate__fadeOut">

<div v-show="show">hello world</div>

</transition>

<button @click="handleClick">动画使用</button>
</div>

<script>
var app = new Vue({
el: '#app',
data: {
show:true,
},
methods:{
handleClick(){
this.show = !this.show
}
}
})
</script>
</body>
</html>

vue 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
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>velocity 使用</title>

<script src="./vue.js"></script>
<script src="./velocity.min.js"></script>
</head>
<body>
<div id="app">
<!-- 动画生命周期钩子
before-enter、enter、after-enter
before-leave、leave、after-leave
-->
<transition
name="fade"
@before-enter="handleBeforeEnter"
@enter="handleEnter"
@after-enter="handleAfterEnter"
>

<div v-show="show">hello world</div>

</transition>

<button @click="handleClick">js动画</button>
</div>

<script>
var app = new Vue({
el: '#app',
data: {
show:true,
},
methods:{
handleClick(){
this.show = !this.show
},
handleBeforeEnter(el){
// el.style.color = 'red';
el.style.opacity = 0;
},
handleEnter(el,done){
// setTimeout(()=>{
// el.style.color = 'green';
// },2000)
// setTimeout(()=>{
// //4秒后调用done 函数告知动画完成
// done();
// },4000)
Velocity(el,{
opacity:1
},{
duration:1000,
complete:done
})
},
handleAfterEnter(el){
// el.style.color = '#000';
console.log("动画结束")
// el.style.opacity = 1;
}
}
})
</script>
</body>
</html>

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>animate css 使用</title>
<script src="./vue.js"></script>

<style>
.v-enter,v-leave-to {
opacity:0;
}
.v-enter-active,v-leave-active {
transition:opacity 1s;
}
</style>
</head>
<body>
<div id="app">

<transition-group>
<div v-for="item of list" key="item.id">
{{ item.title }}
</div>
</transition-group>

<button @click="handleClick">add</button>
</div>

<script>
var count = 0;
var app = new Vue({
el: '#app',
data: {
list:[]
},
methods:{
handleClick(){
this.list.push({
id:count++,
title:'hello world'
})
}
}
})
</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
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>animate css 使用</title>
<script src="./vue.js"></script>
<style>
/* .v-enter,v-leave-to{
opacity:0;
}
.v-enter-active,v-leave-active{
transition:opacity 1s;
} */
</style>
</head>
<body>
<div id="app">
<!-- 父组件给子组件赋值 -->
<fade :show="show">
<div>hello wolrd</div>
</fade>
<button @click="handleClick">动画使用</button>

</div>

<script>
//动画组件的封装
Vue.component('fade',{
props:{
show:true,
},
template:`
<transition @before-enter='handleBeforeEnter' @enter='handleEnter'>
<slot v-if="show"></slot>
</transition>
`,
methods:{
handleBeforeEnter(el){
el.style.color = 'red';
},
handleEnter(el,done){
setTimeout(()=>{
el.style.color = 'green';
done();
},2000)
}
}
})

var app = new Vue({
el: '#app',
data: {
show:true,
},
methods:{
handleClick(){
this.show = !this.show
}
}
})
</script>
</body>
</html>