计算属性:(一个变量的值, 依赖另外一些数据计算而来的结果)
语法:computed:{"计算属性名" (){return "值"}}
完整写法:computed:{"属性名":{set(值){ },get(){return "值"}}}
注意:计算属性也是vue数据变量, 所以不要和data里重名, 用法和data相同
计算属性, 基于依赖项的值进行缓存,依赖的变量不变, 都直接从缓存取结果
<template>
<div>
<span>全选:</span>
<input type="checkbox" v-model="isAll" />
<button @click="btn">反选</button>
<ul>
<li v-for="(val, index) in arr" :key="index">
<input type="checkbox" v-model="val.c" />
<span>{{ val.name }}</span>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
arr: [
{
name: '苹果',
c: false,
},
{
name: '香蕉',
c: false,
},
{
name: '橘子',
c: false,
},
{
name: '橙子',
c: false,
},
],
}
},
computed: {
isAll: {
set(val) {
this.arr.forEach((obj) => (obj.c = val))
},
get() {
return this.arr.every((val) => val.c === true)
},
},
},
methods:{
btn() {
this.arr.forEach(obj=>obj.c = !obj.c)
}
}
}
</script>
侦听器watch:(可以侦听data/computed属性值的改变)
语法:watch:{"被侦听的属性名"(newval,oldval){ }}
深度侦听、立即执行(侦听复杂类型, 或者立即执行侦听函数)
语法:watch:{"要侦听的属性名":{handler(newval,oldval){},deep:true,immediate:true}}
<template>
<div>
<input type="text" v-model="use.name" />
<input type="text" v-model="use.age" />
</div>
</template>
<script>
export default {
data() {
return {
use:{
name: '',
age:0
}
}
},
watch: {
use:{
handler(newVal,oldVal) {
console.log(newVal,oldVal);
},
deep:true,
immediate:true
}
}
}
</script>
<style></style>
watch和computed的区别
- computed一定有返回值,而watch不需要返回值
- computed是依赖的数据发生改变时重新调用, watch是监听的响应式数据发生改变时重新调用
组件的使用(每个组件都是一个独立的个体, 代码里体现为一个独立的.vue文件)
注册方式:
- 全局注册:(main.js中)
- 语法:1、import 组件对象 from 'vue文件路径' 2、Vue.component("组件名",组件对象)
- 局部注册:(vue文件内)
- 语法:1、import 组件对象 from 'vue文件路径' 2、export default { components:{"组件名":组件对象}}
组件-scoped作用:
- 当前组件内标签都被添加 data-v-hash值 的属性
- css选择器都被添加 [data-v-hash值] 的属性选择器
组件通信
父传子:(被引入的是子)
- 子组件创建props定义变量,准备接收: props:[ string ]
- 父组件引入组件,注册组件,使用组件传值
父向子可以配合循环
单向数据流:
- 从父到子的数据流向, 叫单向数据流(子组件修改, 不通知父级, 造成数据不一致性)
- Vue规定props里的变量, 本身是只读的
子向父(子组件触发父自定义事件方法)
- 父组件内, 绑定自定义事件和事件处理函数
- 子组件内, 恰当的时机, 触发父组件绑定的自定义事件, 导致父methods里事件处理函数执行(通过this.$emit('父组件创建的自定义事件名',需要的参数))
无关系的组件通信:
- src/EventBus/index.js – 创建空白Vue对象并导出(监听和触发事件)
- 在要接收值的组件(List.vue) eventBus.$on('事件名', 函数体)
- 在要传递值的组件(MyProduct.vue) eventBus.$emit('事件名', 值)
<template>
<ul class="my-product">
<li v-for="(item, index) in arr" :key="index">
<span>{{ item.proname }}</span>
<span>{{ item.proprice }}</span>
</li>
</ul>
</template>
<script>
import eventBus from '../eventBus'
export default {
props: ['arr'],
created () {
eventBus.$on('send',(index,price)=>{
this.arr[index].proprice > 1 &&
(this.arr[index].proprice = (this.arr[index].proprice - price).toFixed(2))
})
}
}
</script>
<style>
.my-product {
width: 400px;
padding: 20px;
border: 2px solid #000;
border-radius: 5px;
margin: 10px;
}
</style>
------------------------------------------------------------------------------
<template>
<div>
<div style="float: left">
<myproduct
v-for="(obj, index) in list"
:key="obj.id"
:title="obj.proname"
:price="obj.proprice"
:intro="obj.info"
:index="index"
@sub="sub"
></myproduct>
</div>
<div style="float: left">
<listS :arr="list"></listS>
</div>
</div>
</template>
<script>
import listS from './components/list.vue'
import myproduct from './components/myproduct'
export default {
data() {
return {
list: [
{ id: 1, proname: '超级好吃的棒棒糖', proprice: 18.8, info: '开业大酬宾, 全场8折' },
{ id: 2, proname: '超级好吃的大鸡腿', proprice: 34.2, info: '好吃不腻, 快来买啊' },
{id: 3,proname: '超级无敌的冰激凌',proprice: 14.2,info: '炎热的夏天, 来个冰激凌了',},
],
}
},
components: {
myproduct,
listS
},
methods: {
sub(index, price) {
// this.list[index].proprice > 1 &&
// (this.list[index].proprice = (this.list[index].proprice - price).toFixed(2))
},
},
}
</script>
<style></style>
-----------------------------------------------------------------------------------
<template>
<div class="my-product">
<h3>标题: {{ title }}</h3>
<p>价格: {{ price }}元</p>
<p>{{ intro }}</p>
<button @click="fn">砍一刀</button>
</div>
</template>
<script>
import eventBus from '../eventBus'
export default {
props: ['index','title', 'price', 'intro'],
methods: {
fn() {
eventBus.$emit('send',this.index,1)
}
}
}
</script>
<style>
.my-product {
width: 400px;
padding: 20px;
border: 2px solid #000;
border-radius: 5px;
margin: 10px;
}
</style>