面试题:计算属性和方法有什么区别?
计算属性本质上是包含getter和setter的方法 当获取计算属性时,实际上是在调用计算属性的getter方法。vue会收集计算属性的依赖,并缓存计算属性的返回结果。只有当依赖变化后才会重新进行计算。特别需要注意这句话,只有依赖发生改变的时候才会重新计算。只有依赖发生改变的时候才会重新计算。
方法没有缓存,每次调用方法都会导致重新执行。 计算属性的getter和setter参数固定,getter没有参数,setter只有一个参数。而方法的参数不限。 由于有以上的这些区别,因此计算属性通常是根据已有数据得到其他数据,并在得到数据的过程中不建议使用异步、当前时间、随机数等副作用操作。 实际上,他们最重要的区别是含义上的区别。计算属性含义上也是一个数据,可以读取也可以赋值;方法含义上是一个操作,用于处理一些事情。
完整的计算属性书写:
computed: {
propName: {
get(){
// getter
},
set(val){
// setter
}
}
}
只包含getter的计算属性简写:
computed: {
propName(){
// getter
}
}
下面来看具体的例子 app.vue
<template>
<div>
<h1>App组件</h1>
<h2>{{ count }}</h2>
<p>姓:{{ firstName }}</p>
<p>名:{{ lastName }}</p>
<p>全名:{{ fullName }}</p>
<p>全名:{{ fullName }}</p>
<p>全名:{{ fullName }}</p>
<p>全名:{{ fullName }}</p>
<p>全名:{{ fullName }}</p>
<button @click="fullName = '王麻子'">修改姓名为王麻子</button>
<button @click="count++">count++</button>
</div>
</template>
<script>
export default {
data() {
return {
firstName: "亮",
lastName: "哥",
count: 0,
};
},
computed: {
fullName: {
get() {
console.log("fullname called");
return this.firstName + " " + this.lastName + Date.now();
},
set(val) {
console.log("正在设置全名", val);
this.firstName = val[0];
this.lastName = val.substr(1);
},
},
},
methods: {
getFullName() {
console.log("method called");
return this.firstName + " " + this.lastName;
},
},
};
</script>
1.上面计算属性的简单写法就是
fullName(){
return this.firstName + " " + this.lastName
}
因为是计算属性,可以直接使用{{fullName}}就拿到了属性的值。而不是使用{{fullName()}}
2.计算属性的完整写法其实和常规的属性写法一样。计算属性,也只有当前属性的依赖发生改变的时候才会重新计算。在当前的例子里面就是firstName和lastName发生改变的时候才会重新计算,而如果你用上面的getFullName这样的方法去获取属性的时候,不论firstName和lastName是否发生了改变,只要调用方法,都会运行一遍,性能会差一些。
3.计算属性里面不能加上Date.now(),随机数这些东西,因为并不是计算属性获取的方法并不是每次都运行的,只有依赖发生改变的时候才运行。
4.注意一点计算属性收集的依据只能是响应式数据。比方说下面的例子Date.now()并不是响应式数据。他的改变并不会导致计算属性重新计算。下面只有firtName 和 lastName改变才会重新计算属性。
fullName(){
return this.firstName + " " + this.lastName + Date.now(),
}
fullName: {
get() {
console.log("fullname called");
return this.firstName + " " + this.lastName;
},
set(val) {
console.log("正在设置全名", val);
this.firstName = val[0];
this.lastName = val.substr(1);
},
},
5.计算属性强调的是属性,而方法强调操作。
6.其实计算属性都可以改成方法的形式,只不过计算属性比方法多了一层数据的缓存,即当依赖项不发生改变的时候,不会重新计算。
7.计算属性可以 $route 作为依赖
计算属性的完整写法
完整的计算属性书写:
computed: {
propName: {
get(){
// getter
},
set(val){
// setter
}
}
}
只包含getter的计算属性简写:
computed: {
propName(){
// getter
}
}
icon 组件的创建
app.vue 中的代码
<template>
<div>
<h1>App组件</h1>
<Icon type="arrowDown" />
</div>
</template>
<script>
import Icon from "./components/Icon";
export default {
components: {
Icon,
},
};
</script>
<style scoped>
.iconfont {
font-size: 26px;
color: red;
}
</style>
1.默认style加上 scoped,在当前类写的选择器只能对当前的组件有效,vue为了解决在父组件中可以改变子组件的样式,内部进行了处理,可以改变子组件的根元素。可以利用选择器子组件的根元素。
icon.vue
<template>
<i class="iconfont" :class="fontClass"></i>
</template>
<script>
const classMap = {
home: "iconzhuye",
success: "iconzhengque",
error: "iconcuowu",
close: "iconguanbi",
warn: "iconjinggao",
info: "iconxinxi",
blog: "iconblog",
code: "iconcode",
about: "iconset_about_hov",
weixin: "iconweixin",
mail: "iconemail",
github: "icongithub",
qq: "iconsign_qq",
arrowUp: "iconiconfonticonfonti2copy",
arrowDown: "iconiconfonticonfonti2",
empty: "iconempty",
chat: "iconliuyan",
};
export default {
props: {
type: {
type: String,
required: true,
},
},
computed: {
// 图标类样式
fontClass() {
return classMap[this.type];
},
},
};
</script>
<style scoped>
@import "//at.alicdn.com/t/font_2164449_nalfgtq7il.css";
.iconfont {
color: inherit;
font-size: inherit;
}
</style>
- 关于字体图标的使用,需要在字体图标网站新建一个项目,然后在style 里面导入iconfont的地址。
- 这里就是用到了计算属性,因为字体图标本身的使用使用到的真实类的类名不太明显,所以这里的做法从外部传入一个好分辨的类型type,然后根据classMap计算出fontClass的属性,最后动态绑定到fontClass上面就完成了。
- class 可以动态绑定的数据结构包括 字符串,对象,数组。
组件内部的样式由父组件决定的问题
我们开发的过程中有时会遇到内部的组件样式由外部决定,而且这个样式可能比较多,或者是内部不太好处理,需要外部去处理,该如何解决呢?
按照之前说由于样式的后面都加了scoped,按理说我们不能从外部去通过选择器去直接控制组件内部的样式,vue 为了解决这个问题,让父组件的最外层可以去控制子组件的最高一层,详见下面的图例。原理其实就是在内部的最高一层标签上也加了外层的类样式。
如何测试组件
1.每个组件建一个文件夹,比方说pager文件夹,下面index.vue 放的是组件的代码,test.vue里面放的是测试代码。
2.每次测试时候要先 cd 到当前的项目文件夹,就是package.json 所在文件夹,然后执行
vue serve ./src/components/test.vue 即可进行测试。
- 还可以在package里面配置脚本
"test:Avatar": "vue serve ./src/components/Avatar/test.vue",运行的时候只要输入npm run test:Avatar即可。