计算属性

计算属性就是当其依赖属性的值发生变化时,这个属性的值会自动更新,与之相关的DOM部分也会同步自动更新。当有数据需要经过复杂逻辑计算时,可以使用计算属性

简单使用 getter语法糖

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
<template>
<div>
<p>{{allPrice}}</p>
</div>
</template>

<script>
export default{
name:'compute',
data() {
return{
shops:[
{name:'苹果',price:35},
{name:'西瓜',price:15},
{name:'香蕉',price:25},
{name:'菠萝',price:45},
]
}
},
computed:{
//将计算逻辑以函数形式写在 computes中 在template中使用时不需要加(),直接当成属性使用即可
allPrice(){
let res = 0
for(let shop of this.shops){
res+=shop.price
}
return res
}
},
methods:{

}
}
</script>

<style>
</style>

完整使用 getter与setter, 计算属性一般是不使用set方法的,所以通常使用上面的getter语法糖形式

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
<template>
<div>
<p>{{allPrice}}</p>
</div>
</template>

<script>
export default{
name:'compute',
data() {
return{
shops:[
{name:'苹果',price:35},
{name:'西瓜',price:15},
{name:'香蕉',price:25},
{name:'菠萝',price:45},
]
}
},
computed:{
allPrice{
setter(newValue){
//set 方法是监视对应的属性值,当值发生变化时会自动回调set方法
console.log(newValue)
},
getter(){
let res = 0
for(let shop of this.shops){
res+=shop.price
}
return res
}
}
},
methods:{

}
}
</script>

<style>
</style>

注意:methods与computed 都能够实现计算操作,但是computed的优势在于, computed有缓存,它会把计算好的值做了一层缓存,它会观察对应的值有没有变化,如果有变化则再去清空缓存并计算,这样就提升了程序运行的效率

组件

组件是Vue中的一个重要概念,在vue中,每一个界面都是以组件的形式存在的,而组件中还可以再包含组件

全局组件

如果网页中某一个部分在多个场景中经常使用,我们就可以将这个部分抽出来作为一个组件进行复用。

例如我们这里有两个页面,里面的内容分别对应网页的头部和底部。如果在多个界面都使用到了这两个部分,我们就可以把它注册成全局组件,这样就可以在所有界面都使用它

  1. 首先在main.js 中引入文件,import 变量名 from 文件位置

  1. 随后使用 Vue的 compoonet 注册组件 ,第一个值 就是注册的全局组件的名字,我们可以在其他界面通过这个名字来调用这个组件,第二个值就是绑定对应的组件,通过上面的import 定义的名字进行绑定

  1. 最后就可以在任意地方来调用这个组件了

父子组件通信

  1. 父组件向子组件传值:

以上面的header 为例,再创建一个组件 Header_child 作为它的子组件(注册组件的步骤省略)

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
<template>
<div>
{{Smessage}}
</div>
</template>

<script>
name:'Header_child'
export default{
data() {
return{
Smessage:this.message
}
},
// props 里的数据只做展示用,如需在页面上进行交互修改则需要绑定到data
props:{ //在props 中声明父组件传进来的数据
message:{ // 定义属性,父组件向子组件的message传值
type: String, //声明传进来的数据类型
default: 'ss' //声明默认值
}
},
}
</script>

<style>
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<div>
<HeaderC :message="saySomething"></HeaderC> <!-- 使用v-bind 指令,将data中的数据绑定给子组件的 message 属性-->
</div>
</template>

<script>
export default {
name: "header",
data() {
return {
saySomething: "Welcome to Your Vue.js App"
};
},
};
</script>

<style>
</style>
  1. 子组件向父组件传值:

    第一种方式 由于父组件传值使用过v-bind 绑定的,之前学习过双向绑定,所以当子组件的数据发生变化时,父组件对应的值也会变化,所以在子组件中修改绑定的值,即可完成传参

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    <template>
    <div>
    <input type="text" v-model="Cmessage" />
    <button @click="sayOther">确定</button>
    </div>
    </template>

    <script>
    name:'Header_child'
    export default{
    data() {
    return{
    Cmessage:''
    }
    },
    methods:{
    sayOther(){
    this.message = this.Cmessage
    }
    },
    props:{ //在props 中声明父组件传进来的数据
    message:{ // 定义属性,父组件向子组件的message传值
    type: String, //声明传进来的数据类型
    default: 'ss' //声明默认值
    }
    },
    }
    </script>

    <style>
    </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
<template>
<div>
接收到的数据:{{this.showMessage}}
<input type="text" v-model="Cmessage" />
<button @click="sayOther">确定</button>
</div>
</template>

<script>
name:'Header_child'
export default{
data() {
return{
showMessage:this.message
Cmessage:''
}
},
methods:{
sayOther(){
this.$emit("ChildchangeSay",this.Cmessage)// this.$emit是为了触发父组件的ChildchangeSay事件,Cmessage是子组件传递的数据
}
},
props:{
message:{
type: String,
default: 'ss'
}
},
}
</script>

<style>
</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
<template>
<div>
<HeaderC :message="saySomething" @ChildchangeSay="FatherGetSay"></HeaderC>
</div>
</template>

<script>
export default {
name: "header",
data() {
return {
saySomething: "Welcome to Your Vue.js App"
};
},
methods:{
FatherGetSay(val){
this.saySomething = val
}
}
};
</script>

<style>
</style>
  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
<template>
<div>
<Button @click="btnclick">点击调用子组件方法</Button>
<HeaderA ref="child"/> <!-- 3.设置ref属性 -->
</div>
</template>

<script>
import HeaderA from '../Header_child.vue' //1.导入子组件

export default {
name: "header",
components:{//2. 挂载至当前组件下
HeaderA
},
data() {
return {
saySomething: "Welcome to Your Vue.js App"
};
},
methods:{
btnclick() {
console.log(this.$refs.child)
},
}
};
</script>

<style>
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<div>我是子组件</div>
</template>
<script>
export default {
name:"Header_child",
methods: {
sing() {
console.log('我是子组件的方法');
},
},
};
</script>

使用 this.$refs.属性名 即可访问子组件

  1. 子组件访问父组件,与上面相同 使用 $parent 属性访问
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
<template>
<div>
<h1>我是子组件</h1>
<button @click="btnclick">点击调用父组件方法</button>
</div>
</template>

<script>
name:'Header_child'
export default{
data() {
return{

}
},
methods:{
btnclick() {
console.log(this.$parent)
},
sayHello(){
console.log('abcd')
},
},
}
</script>

<style>
</style>

插槽

插槽类似于拼图,可以在一个较大的模板中,定义一个可活动区域插槽,当这个区域想要更换内容时,往里面插入不同的组件即可,

1
2
3
4
5
<template>
<slot name="left">左边</slot>
<slot name="center">中间</slot>
<slot name="right">右边</slot>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
<div id="all">

<com>
<template>
<span v-slot="left">啊啊</span>
<span v-slot="cebter">zz</span>
<span v-slot="right">啊啊</span>
</template>
</com>

</div>
</template>

<script>

import com from './test.vue'
export default {
name: "Header",
components:{
com
}

</script>

当父组件想要改变插槽中的内容或数据时,可以通过属性传参

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<slot :data="list"> //定义data 属性,并赋值list
<span v-for="item in list">{{item}}</span>
</slot>
</template>

<script>
export default{
name:'test',
data() {
return{
list:['张三','李四','王五']
}
}
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<div id="all">
<com>
<template slot-scope="slot"> <!-- 通过定义的 slot 来引用插槽对象,再通过插槽对象即可访问插槽中的数据 -->
<button v-for="item in slot.data"></button>
</template>
</com>
</div>
</template>

<script>
import com from './test.vue'
export default {
name: "Header",
components:{
com
}
};
</script>