首先回答一下上篇文章的问题
1.为什么v-for的key不用索引呢?
首先,:key是用于给v-for颁发唯一标识的,用于性能优化,其值最好是不重复且唯一.
如果使用索引作为key的值,当往数组中再插入一个值,或者删除一个值的时候,索引就会跟随值的改变而改变,此时v-for渲染出来的位置就有可能打乱,比如删除一个当前值,结果删除了后面那个
所以,在使用:key时最好使用一个唯一的,不重复的值,比如id,这样就能保证准确
2.数组更新为何有时v-for不触发呢?
vue底层只能检测到数组顺序/位置改变/数量变化,但值被重新赋予,vue不能检测,例如字面量方法直接把值改了,根本检测不到
要解决这个问题,使用this.$set或Vue.set(),两个方法都可以解决
一.组件
1.什么是组件
组件是可复用的Vue实例,可以封装标签,样式和js代码,把页面可重复使用的部分封装为组件,方便项目开发与维护
2.如何使用
第一步:注册
在项目文件夹中的components文件夹中创建需要封装的组件(即vue文件)
在此创建test.vue文件,
第二步:引入
第三步:注册
两种注册方式
1.全局注册
2.局部注册
第四步:使用
根据注册时的组件名,用作标签
3.scoped作用
给组件内的style标签增加scoped可以让样式只在当前组件内生效
原理:增加scoped属性后,就会在对应组件的标签上增加一个随机生成的data-v开头带随机哈希值的属性,这样就能保证样式只对当前组件生效.
二.通信
1.父向子传值
子组件 props 接收值
例如:父组件中定义变量str,在组件标签上将值传递到子组件上
<template>
<div>
<test :abc="str"> </test>
</div>
</template>
<script>
import test from "./components/test.vue";
// import vue from "vue";
// vue.component("test", test);
export default {
components: {
test,
},
data() {
return {
str: "我是传过去的值",
};
},
};
</script>
<style>
</style>
子组件使用props接收变量,变量名需要与父组件传递来的属性名相同
<template>
<div>
{{ abc }}
</div>
</template>
<script>
export default {
props: ["abc"],
};
</script>
<style>
</style>
2.子向父通信 配合v-for循环
例如:
父组件:
<template>
<div>
<test v-for="(item, index) in arr" :key="index" :val='item'> </test>
</div>
</template>
<script>
import test from "./components/test.vue";
// import vue from "vue";
// vue.component("test", test);
export default {
components: {
test,
},
data() {
return {
arr: [1, 23, 4, 324, 5421, 23421, 24, 234, 24, 42],
};
},
};
</script>
<style>
</style>
子组件:
<template>
<div>
{{ val }}
</div>
</template>
<script>
export default {
props: ["val"],
};
</script>
<style>
</style>
注:也可以直接将数组传进子组件,然后在子组件中遍历
3.单向数据流
在vue中需要遵循单向数据流的原则
- 父组件的数据发生改变,子组件会跟随改变
- 子组件不能直接修改父组件传递来的props,props是只读的
注意:如果父组件传给子组件一个对象,或一个数组,引用类型数据是不会报错的,因为父组件相当于传了一个地址过去,互相更新
总结:
props变量本身是只读的不能重新赋值
从父组件->子组件的数据流向叫单向数据流
子组件修改不通知父级,会造成数据不一致
4.组件通信-子向父
将子组件的值传递给父级使用,再通过单向数据流影响子组件
使用自定义事件名
例如:
父组件:
<template>
<div>
<!--1.由此处开始,父组件将数组内的值传给子组件 :val='item'-->
<!-- 7.自定义事件在这里生效,触发delFn方法 -->
<!--10.更新新数组,影响子组件 -->
<test
v-for="(item, index) in arr"
:key="index"
:val="item"
@delEvent="delFn"
>
</test>
</div>
</template>
<script>
import test from "./components/test.vue";
// import vue from "vue";
// vue.component("test", test);
export default {
components: {
test,
},
data() {
return {
arr: [1, 23, 4, 324, 5421, 23421, 24, 234, 24, 42],
};
},
methods: {
//8.在这里定义delFn方法
delFn(min) {
//9.在这里操作数组
this.arr.splice(
this.arr.findIndex((item) => item === min),
1
);
},
},
};
</script>
<style>
</style>
子组件:
<template>
<div>
<!-- 3.渲染val值在DOM中 -->
<span>{{ val }}</span>
<!-- 4.点击按钮触发btn()方法,并传参val -->
<button @click="btn(val)">delete</button>
</div>
</template>
<script>
export default {
//2.子组件接收到值val
props: ["val"],
methods: {
//5.在此处定义btn()方法
btn(who) {
//6.利用this.$emit()方法将自定义事件名,与val值传递出去
this.$emit("delEvent", who);
},
},
};
</script>
<style>
</style>
这样就可以完成一个简单的删除功能,一般删除的话需要传id值,这里就简单使用原值代替一下
思考(有答案可以写在评论区哦)
为什么vue组件的data是个函数呢?
有答案的小伙伴欢迎评论区哦,答案在下期揭晓,未完待续...