1. 组件的嵌套、与传值
1.1 组件嵌套
开发中vue前端会编写大量的组件,往往大组件代表的就是页面,大的组件下面会包含引入小组件,小组件往往就是一个页面的部分功能代码,例如:导航条、购物车、弹窗、侧边栏、轮播图等,其实就是用到了组件嵌套的方式,在父级组件中子组件。
接下来,我们组件嵌套的例子:
首先分别创建父组件和子组件文件:
在App.vue顶级组件所在的目录下有一个components文件下,我们在该文件夹下创建一个名为Home的父级组件,接着继续在components文件而内创建一个名为common的文件夹用来存放home的子组件,在该文件夹内再创一个名为Menu的子组件。
先编写子组件Menu的代码:
<template>
<div>
<h3>子组件Menu:</h3>
</div>
</template>
<script>
export default {
name: "Menu"
}
</script>
<style scoped>
</style>
然后在父组件中调用上面写的子组件Menu:
<template>
<div><h2>父组件Home:</h2>
<div>
<!--3. 使用子组件-->
<Menu></Menu>
</div>
</div>
</template>
<script>
// 1. 导入子组件Menu
import Menu from "./homeson/Menu"
export default {
name: "Home",
data() {
return {
num1: 10,
}
},
components: {
// 2 注册子组件
Menu
}
}
</script>
<style scoped>
</style>
最后在顶级组件App中调用父组件Home:
<template>
<div>
<div><h1>顶级组件App:</h1></div>
<!--3. 使用父组件-->
<Home></Home>
</div>
</template>
<script>
// 1. 导入父组件Home
import Home from './components/Home'
export default {
name: "App",
components: {
// 2 注册父组件
Home
}
}
</script>
<style scoped>
</style>
效果:
1.2 嵌套组件之间的传数据
1.2.1 父组件的数据传递给子组件
接着上面的例子我们来实现父组件传数据给子组件
步骤可分为三步:
-
在父组件中,调用子组件的组名处,使用属性值的方式往下传递数据
<template> <div><h2>父组件Home:</h2> <div> <button @click="num1--">-</button> <input type="text" v-model="num1"> <button @click="num1++">+</button> ==<Menu :homenum1="num1" homemsg="home里面的内容"></Menu>== </div> </div> </template>
上面表示在父组件调用Menu子组件的时候传递了2个数据,如果要传递变量[变量可以各种类型的数据],属性名左边必须加上冒号
:
,同时,属性名是自定义的,会在子组件中使用;如果要传递普通字符串数据,则不需要加上冒号。 -
在子组件中接受上面父组件传递的数据,需要在vm组件对象中,使用props属性类接收。
-
在子组件中的template中使用父组件传递过来的数据
上面只表示了步骤,具体的数据和方法可以自己设定
效果:
f
使用父组件传递数据给子组件时, 注意一下几点:
-
传递数据是变量,则需要在属性左边添加冒号.
传递数据是变量,这种数据称之为"动态数据传递"
传递数据不是变量,这种数据称之为"静态数据传递"
-
父组件中修改了数据,在子组件中会被同步修改,但是,子组件中的数据修改了,是不是影响到父组件中的数据.
这种情况,在开发时,也被称为"单向数据流"(Home指向Menu)
1.2.2 子组件传数据给父组件
跟上面一样分为三个步骤:
-
在子组件中,通过
this.$emit()
来调用父组件中定义的事件,一般写在watch内:watch:{ num1(){ this.$emit("menuData",this.num1) } }
Menu组件内所有代码:
<template> <div> <h3>子组件Menu:</h3> <button @click="num1++">Menu组件里的num1={{num1}}</button> </div> </template> <script> export default { name: "Menu", data() { return { num1:10, } }, props: ["homenum1", "homemsg"], watch:{ num1(){ this.$emit("menuData",this.num1) } } } </script> <style scoped> </style>
-
父组件中使用子组件处,声明一个和子组件中
this.$emit("自定义事件名称")
对应的事件@menuData
,给该事件绑定一个任意的自定义方法changenum1
。<Menu @menuData="changenum1"></Menu>
-
script内书写自定义方法的具体代码,注意子组件传过来几个值,方法内就用几个参数接收。
methods:{ changenum1(v1){ this.num1=v1 } }
Home内所有代码
<template> <div><h2>父组件Home:</h2> <button @click="num1++">Home组件里的num1={{num1}}</button> <Menu @menuData="changenum1"></Menu> </div> </template> <script> import Menu from "./homeson/Menu" export default { name: "Home", data() { return { num1: 10, } }, components: { Menu }, methods:{ changenum1(v1,v2){ this.num1=v1 console.log(v1,v2) } } } </script> <style scoped> </style>
效果:
也是单向的数据流,Menu指向Home,修改子组件的值,父组件跟着改变:
修改父组件的值,子组件不变:
补充:
js内使用for循环的时候,关键字in和of的区别:
for...in
:遍历出来的数据是当前数组的下标或者是对象的属性名称(0、1、2/name、age、gender)for...of
:遍历出来的数据是当前数组的元素或者是对象的属性值('a'、'b'、'c'/'tom'、18、’male‘)