Vue 总结笔记

显示内容

1
v-text  和 {{}} 的作用一样 , v-html

以上的这三种都可以写成js的表达式,而不仅仅是一个变量
例如:

1
2
3
<div> {{ name + 'Js' }} </div>
<div v-text="name + 'Js'"></div>
<div v-html="name + 'Js'"></div>

1
2
3
watch     侦听器(当某字段发生变化时候,可以写侦听器做出相应的动作)
computed 计算属性(具有缓存功能)
methods 方法

计算属性的get和set方法

样式绑定

条件渲染

1
2
v-if、v-else、v-else-if
v-show

vue会最大的复用已有的内容,加上key值就不会复用

列表循环渲染

每个循环项中最好都加上不同的key,最好不使用列表的index作为key值
当我们对数组进行操作的时候,我们不应该使用下标的方式去访问数组的元素。应该使用vue官方提供的方法来操作,pop、push、shift、unshift、splice、sort、reverse
模版占位符 template

对象循环渲染

set方法

使用set方法为对象中添加值或者修改值

改变数组值

改变数组值的三种方式
1.改变数组的引用
2.使用vue自带的方法
3.使用set方法

改变对象值

改变对象值的三种方式
1.改变数组的引用
2.使用set方法

is的使用

is的使用,可以用来解决一些h5标签的问题(例如,在h5中tbody下必须是tr,但现在tbody下是子组件,那么这就是不符合规范的。我们可以使用is标签来解决这样的问题, 这样出来的结果是子组件的,同时我们也满足了h5的写法)

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
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<!--引入vue.js-->
<script src="./vue.js"></script>

</head>
<body>
<div id="app">
<table>
<tbody>
<zujian></zujian>
<zujian></zujian>
<zujian></zujian>
</tbody>
</table>
</div>
<script type="text/javascript">
Vue.component('zujian', { // 定义一个全局组件
'template':'<tr><td> 子组件li标签 </td></tr>'
})

var app = new Vue({ // 实例化一个Vue
el: "#app", // 使用el绑定
data :{
"inputValue" : ""
}
})
</script>
</body>
</html>

以上的写法是可以正常运行的,但是我们审查元素看的时候,看见的不是标准的table下tbody,tbody下tr的格式,这个在h5是不允许的,tbody下只能四tr。于是我们可以使用is来解决这种问题

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
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<!--引入vue.js-->
<script src="./vue.js"></script>

</head>
<body>
<div id="app">
<table>
<tbody>
<tr is='zujian'></tr> <!-- 使用is来解决这种问题 -->
<tr is='zujian'></tr>
<tr is='zujian'></tr>
</tbody>
</table>
</div>
<script type="text/javascript">
Vue.component('zujian', { // 定义一个全局组件
'template':'<tr><td> 子组件li标签 </td></tr>'
})

var app = new Vue({ // 实例化一个Vue
el: "#app", // 使用el绑定
data :{
"inputValue" : ""
}
})
</script>
</body>
</html>

在子组件中使用data

在子组件中定义data的时候,data必须是一个函数,而不是一个对象。这样能让每个子组件有属于自己的数据,而不相互影响

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<!--引入vue.js-->
<script src="./vue.js"></script>

</head>
<body>
<div id="app">
<table>
<tbody>
<tr is='zujian'></tr>
<tr is='zujian'></tr>
<tr is='zujian'></tr>
</tbody>
</table>
</div>
<script type="text/javascript">
Vue.component('zujian', { // 定义一个全局组件
data: function(){ // data必须是一个函数,而不是一个对象
return {
zizujian_value : "123456789"
}
},
'template':'<tr><td> 子组件的值 zizujian_value </td></tr>',
})

var app = new Vue({
el: "#app",
data :{
"inputValue" : ""
}
})
</script>
</body>
</html>

ref的使用

当ref用在普通html上面的时候,我们通过this.$refs.名称获取到的是这个dom元素,而当ref用在子组件上面的时候,我们通过this.$refs.名称获取到的是子组件的引用。

在dom中使用

例如: 获取一个div中的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
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<!--引入vue.js-->
<script src="./vue.js"></script>

</head>
<body>
<div id="app">
<div ref='ref_test' @click='divclick'> div中的内容 </div> <!-- 定义一个click事件,并且定义一个ref -->
</div>
<script type="text/javascript">
var app = new Vue({
el: "#app",
methods:{
divclick:function(){ // 当ref用在普通html上面的时候,我们通过this.$refs.名称获取到的是这个dom元素
alert(this.$refs.ref_test.innerHTML)
}
}
})
</script>
</body>
</html>

在组件中使用

例如: ref使用在组件上

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
<html>
<head>
<title> Vue实例 </title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root" @click="zujian_click">
<zujian ref="zizujian_ref"></zujian>
</div>
<script>
Vue.component("zujian", {
data:function(){
return{
zizujian_value:" 1~100 "
}
},
template:"<span> 子组件的内容,子组件的值{{ zizujian_value }} </span>"
});
var vm = new Vue({
el:'#root',
methods:{
zujian_click:function(){
alert(this.$refs.zizujian_ref.zizujian_value)
}
}
})
</script>
</body>
</html>

父子组件的数据传递

父组件往子组件传递数据

使用属性的方式来传递数据,在子组件中使用props来接收数据。在vue中父组件往子组件传递的值在子组件是不能修改的,这样的操作vue是不允许的。正确的做法是将值赋予给一个新的子组件的变量,然后对这个子组件的data中的变量进行操作即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<html>
<head>
<title> Vue实例 </title>
<script src="./vue.js"></script>
</head>
<body>
<ul id="root">
<zizujian :it="item" v-for="item in data_list"></zizujian>
</ul>
<script>
// 定义一个局部子组件
var zizujian = {
props:['it'],
template:"<li> 局部子组件的文本, 值是{{ it }} </li>"
};

var vm = new Vue({
el:'#root',
components:{
zizujian:zizujian
},
data:{
data_list:[1, 2, 3, 4, 5]
}
})
</script>
</body>
</html>

子组件往父组件传递数据

子组件通过this.$emit事件触发的方式来往父组件传值

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
<html>
<head>
<title> Vue实例 </title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
<zizujian @chufashijian="chufashijian2"></zizujian> <!-- 监听抛出的事件,对应触发父组件的相关方法 -->
</div>
<script>
var zizujian = {
data:function(){
return {
zizujian_value : 100
}
},
template:"<span @click='zujian_click'> 子组件文本, 值: {{ zizujian_value }} </span>", // 子组件中定义是个事件
methods:{
zujian_click:function(){
this.$emit("chufashijian", this.zizujian_value); // 在事件中通过$emit的方式定义一个事件将值抛出
}
}
};
var vm = new Vue({
el:'#root',
components:{
zizujian:zizujian
},
methods:{
chufashijian2:function(zizujian_value){
alert(zizujian_value); // 父组件中取到值
}
}
})

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

组件参数校验

以前的props是一个数组,里面放上一些接收的参数,现在我们可以将props写成对象,来进行值的校验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Vue.component('child', {
porps:{
arg1:[String, Number] // 参数必须是String和Number
}
})


Vue.component('child', {
porps:{
arg1:{
type:String, // 参数必须是String
required:false, // 不是必填项
default:'default value', // 默认值为 default value
vilidator:function(value){ // 值的长度需要大于5
return (value.length > 5)
}
}
}
})

非props

非props指的是父组件传值了,但是子组件不接收,这样的非props有两个特性,1是传的值不能在子组件中使用,另一个就是传值的属性会在html中显示

给组件绑定原生事件

假如目前有一个组件是,这个组件绑定一个click事件,发现没有触发,原因是在组件上绑定原生的事件我们需要使用native,即

非父子组件中的传值

1,vuex
2,使用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
<html>
<head>
<title>非父子组件之间的传值(实现的效果为点击某一个,两者的值都变成一样)</title>
<script type="text/javascript" src="./vue.js"></script>
</head>
<body>
<div id="test">
<zizujian chuanzhigeizizujian='内容1'> </zizujian>
<zizujian chuanzhigeizizujian='内容2'> </zizujian>
</div>

<script type="text/javascript">
Vue.prototype.bus = new Vue() // 新增一个bus属性,属性的值是一个新的Vue实例

Vue.component('zizujian', {
data:function(){ // 数据是单向的,也就是说从父组件传递来的值子组件不能修改,只能复制一份在进行修改,不然会引起警告
return {
jubu_chuanzhigeizizujian:this.chuanzhigeizizujian
}
},
props:{
chuanzhigeizizujian: String // 定义传来的值的类型只能是String
},
template:'<div @click="clickmethod">{{ jubu_chuanzhigeizizujian }}</div>',
methods:{
clickmethod:function(){
this.bus.$emit('change', this.jubu_chuanzhigeizizujian) // 当触发点击事件的时候,就是用我们新定义的bus属性(因为值是Vue实例,所以有$emit)来抛出一个change事件,并传递一个值
}
},
mounted:function(){
var this_ = this // 两个this不能混合,所以定义一个来局分开
this.bus.$on('change', function(msg){ // 当检测到bus属性的change事件被触发的时候
this_.jubu_chuanzhigeizizujian = msg
})
}
})

var app = new Vue({
'el':test
})
</script>
</body>
</html>

插槽

父组件往子组件传值的时候,希望可以传递一些html内容

  1. 原始的做法(得在子组件中使用一种标签,并且加上v-html才能使用)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <html>
    <head>
    <title> 插槽 </title>
    <script type="text/javascript" src="./vue.js"></script>
    </head>
    <body>
    <div id="test">
    <zizujian chuanzhu_shuxing='<p> 这是一段文本 </p>'> </zizujian>
    </div>
    <script type="text/javascript">
    Vue.component('zizujian', {
    props:['chuanzhu_shuxing'],
    template:'<div> <div v-html=chuanzhu_shuxing> </div> </div>'
    })

    var app = new Vue({
    'el':test
    })
    </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
    <html>
    <head>
    <title> 插槽 </title>
    <script type="text/javascript" src="./vue.js"></script>
    </head>
    <body>
    <div id="test">
    <zizujian>
    <p slot="header"> header </p> <!-- 定义两个插槽 -->
    <p slot="footer"> footer </p>
    </zizujian>
    </div>
    <script type="text/javascript">
    Vue.component('zizujian', { // html的内容为插槽header的 + content + 插槽footer + 默认插槽
    template:'<div> <slot name="header"></slot> <p> content </p> <slot name="footer"></slot> <slot name="other">默认内容</slot> </div>'
    })
    var app = new Vue({
    'el':test
    })
    </script>
    </body>
    </html>

作用域插槽

当子组件中有循环,或者子组件的dom结构由父组件决定的时候可以使用作用域插槽

  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
    <html>
    <head>
    <title> 插槽 </title>
    <script type="text/javascript" src="./vue.js"></script>
    </head>
    <body>
    <div id="test">
    <zizujian>
    </zizujian>
    </div>
    <script type="text/javascript">
    Vue.component('zizujian', {
    data:function(){
    return {
    data_list:[1, 2, 3, 4, 5]
    }
    },
    template: // 这里使用了`,可以将代码写在多行
    `<ul>
    <li v-for="item of data_list"> {{ item }} </li>
    </ul>`
    })
    var app = new Vue({
    'el':test
    })
    </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
    <html>
    <head>
    <title> 插槽 </title>
    <script type="text/javascript" src="./vue.js"></script>
    </head>
    <body>
    <div id="test">
    <zizujian>
    <template slot-scope="zidingyimingcheng">
    <li>{{ zidingyimingcheng.item }}</li> <!-- 这里的template、slot-scope是固定写法,item是子组件中传来的值 -->
    <!-- <h3>{{ zidingyimingcheng.item }}</h3> -->
    </template>
    </zizujian>
    </div>
    <script type="text/javascript">
    Vue.component('zizujian', {
    data:function(){
    return {
    data_list:[1, 2, 3, 4, 5]
    }
    },
    template: // 这里使用了`,可以将代码写在多行
    `<ul>
    <slot :item=item v-for="item of data_list"></slot>
    </ul>`
    })
    var app = new Vue({
    'el':test
    })
    </script>
    </body>
    </html>

动态组件与v-once

当我们根据条件来进行组件的显示与不显示的时候,vue的底层会将当前显示的组件销毁,然后在创建要显示的组件。而当我们使用v-once的时候,在切换的时候vue会将上次的结果直接从内存中取出,而不是再去创建,这样在性能上会有所提升。

  1. 不加v-once

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    <html>
    <head>
    <title> 插槽 </title>
    <script type="text/javascript" src="./vue.js"></script>
    </head>
    <body>
    <div id="test">
    <zizujian1 v-if="type === 'zizujian1'"></zizujian1>
    <zizujian2 v-if="type === 'zizujian2'"></zizujian2>
    <button @click='click_btn'>切换</button>
    </div>
    <script type="text/javascript">
    Vue.component('zizujian1', {
    template: '<div> 文本1 </div>'
    })

    Vue.component('zizujian2', {
    template: '<div> 文本2 </div>'
    })

    var app = new Vue({
    'el':test,
    'data':{
    type:'zizujian1'
    },
    methods:{
    click_btn:function(){
    this.type = (this.type == 'zizujian1'? 'zizujian2' : 'zizujian1')
    }
    }
    })
    </script>
    </body>
    </html>
  2. 加上v-once

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    <html>
    <head>
    <title> 插槽 </title>
    <script type="text/javascript" src="./vue.js"></script>
    </head>
    <body>
    <div id="test">
    <zizujian1 v-if="type === 'zizujian1'"></zizujian1>
    <zizujian2 v-if="type === 'zizujian2'"></zizujian2>
    <button @click='click_btn'>切换</button>
    </div>
    <script type="text/javascript">
    Vue.component('zizujian1', {
    template: '<div v-once> 文本1 </div>'
    })

    Vue.component('zizujian2', {
    template: '<div v-once> 文本2 </div>'
    })

    var app = new Vue({
    'el':test,
    'data':{
    type:'zizujian1'
    },
    methods:{
    click_btn:function(){
    this.type = (this.type == 'zizujian1'? 'zizujian2' : 'zizujian1')
    }
    }
    })
    </script>
    </body>
    </html>
  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
    <html>
    <head>
    <title> 插槽 </title>
    <script type="text/javascript" src="./vue.js"></script>
    </head>
    <body>
    <div id="test">
    <!--
    <zizujian1 v-if="type === 'zizujian1'"></zizujian1>
    <zizujian2 v-if="type === 'zizujian2'"></zizujian2>
    -->
    <component :is="type"></component> <!-- 根据type的值来动态加载组件的内容,当type的值是zizujian1的时候就加载zizujian1组件,反之相反 -->
    <button @click='click_btn'>切换</button>
    </div>
    <script type="text/javascript">
    Vue.component('zizujian1', {
    template: '<div v-once> 文本1 </div>'
    })

    Vue.component('zizujian2', {
    template: '<div v-once> 文本2 </div>'
    })

    var app = new Vue({
    'el':test,
    'data':{
    type:'zizujian1'
    },
    methods:{
    click_btn:function(){
    this.type = (this.type == 'zizujian1'? 'zizujian2' : 'zizujian1')
    }
    }
    })
    </script>
    </body>
    </html>

动画效果

transition过度动画

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
<html>
<head>
<title> 样式 </title>
<script type="text/javascript" src="./vue.js"></script>
<style type="text/css">
.v-enter, .v-leave-to { /* 这里的v是默认的前缀,当transition有name属性的时候,v换为name的值。如下举例name="tra",则class则变为 tra-enter、tra-leave-to*/
opacity 0;
}
.v-enter-active, .v-leave-active {
transition: opacity 1s;
}

</style>
</head>
<body>
<div id="test">
<transition> <!-- 如果这里有name属性,那么css中的前缀v就得换为这里name的值。例如name="tra" -->
<div style="background: red" v-if='show'> 内容 </div>
</transition>
<button @click='click_btn'>显示/不显示</button>
</div>
<script type="text/javascript">
var app = new Vue({
'el':test,
'data':{
show:true
},
methods:{
click_btn:function(){
this.show = !this.show
}
}
})
</script>
</body>
</html>

animate

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
<html>
<head>
<title> 样式 </title>
<script type="text/javascript" src="./vue.js"></script>
<link rel="stylesheet" type="text/css" href="./animate.css">
</head>
<body>
<div id="test">
<!--enter-active-class和leave-active-class表示自定义动画,animated表示使用animate,后面跟上想要实现的动画效果
https://daneden.github.io/animate.css/
-->
<transition
enter-active-class='animated swing'
leave-active-class='animated shake'
>
<div v-show='show'> 内容 </div>
</transition>
<button @click='click_btn'>显示/不显示</button>
</div>
<script type="text/javascript">
var app = new Vue({
'el':test,
'data':{
show:true
},
methods:{
click_btn:function(){
this.show = !this.show
}
}
})
</script>
</body>
</html>

velocity

多个元素之间的过度效果

组件的过度效果

未完….待续 つづく