文章目录
- 前言
- 组件化开发
- 父子组件相互传数据
- 父传子:自定义属性
- 子传父:自定义事件
- 父子组件互传案例
- 插槽 slot
- 多个插槽
- 总结
- 组件化开发总结
- Vue组件的基本组成
- 子组件使用的三个步骤
- 父子组件相互传递数据
前言
提示:这里可以添加本文要记录的大概内容:
Vue.js 是一种现代化的前端框架,可以用于构建可复用的组件化应用程序。Vue.js 提供了一种基于组件的架构,使得开发人员可以将应用程序分解为多个可重用的组件。
Vue.js 组件是一个可复用的代码模块,可以在 Vue.js 应用程序中使用。组件包括 HTML 模板、JavaScript 代码和 CSS 样式,并且可以包含其他组件。
Vue.js 组件化开发的主要优势包括:
-
模块化:Vue.js 组件使得应用程序变得更易于管理和维护,可以将应用程序分解为多个小模块,每个模块都有自己的功能和样式。
-
可重用性:组件化开发使得开发人员可以编写可重用的代码片段,可以在不同的项目中使用,并且可以在同一应用程序中多次使用。
-
维护性:组件化开发使得代码更加模块化,更易于维护和测试。
-
性能:在 Vue.js 中使用组件可以提高应用程序的性能,因为它可以在需要时延迟加载组件。
总之,Vue.js 组件化开发是一种高效的方式,可以帮助开发人员构建可维护和可重用的应用程序。
提示:以下是本篇文章正文内容,下面案例可供参考
组件化开发
首先Ctrl+c
停止上面项目访问,新建一个项目
cd ..
:返回上一级
接下来就是把【创建Vue-Cli工程】的过程再来一遍:
完整过程:
- 新建文件夹【vue create 小写名字】:
vue create component
。component(组件化开发) - 选择最后一个:
Manually select features
- 空格去掉倒数第三个:
( * ) Linter / Formatter
- 默认选择3.x
- 选择倒数第二个:
In package.json
- 不保存:
n
出现Successfully代表创建成功
打开项目,进行一些默认操作:
①、用脚手架创建项目时,把脚手架生成的代码删除掉
②、删除App.vue内所有代码,随后输入vue
选择第一个
在template标签中加代码:
<h1>{{ title }}</h1>
在script标签中的data函数的返回对象加代码:
title:'我是根组件'
打开终端输入:npm run serve
,就可以运行了
在components文件夹下新建个子组件TabMenu.vue,名字是驼峰式命名
生成基本结构,输入vue回车,加点代码与样式,这里可以随便写,主要是展示子组件的使用
现在一个根组件(App.vue),一个子组件(TabMenu.vue),运行:
那么如何在根组件中使用子组件呢?
以App.vue根组件,TabMenu.vue子组件为例:
- 导入需要的子组件(在script标签内)
import TabMenu from '@/components/TabMenu.vue'; //@相当于src
- 在components的配置项中注册子组件
components: {TabMenu},
- 在template中以标记的语法使用子组件
<TabMenu></TabMenu>
父子组件相互传数据
在父子组件中如何让他俩可以相互发数据?
以App.vue根组件,Data.vue子组件为例:
父传子:自定义属性
先写先接受数据的一方
- 父给子传数据,先给子组件里面增加一个新个配置项
props
,自定义属性的意思
在components
文件中新建子组件Data.vue(script标签内)
vue生成基本结构后,增加props
配置项
// 数组形式,里面自定义名字props: ['test']
- 在template标签内加上插值语法把上面的自定义名字加上去
<template><div><h1>数据子组件</h1><h1>这是父组件传递给我的数据:{{ test }}</h1></div>
</template>
- 在父组件中再导入该子组件(在script标签内)
import Data from '@/components/Data.vue'
- 在components的配置项中注册子组件
components: {TabMenu,Data}, //TabMenu是另一个子组件,多个子组件用逗号隔开
- 在template中以标记的语法使用子组件
<Data></Data>
父组件App.vue中完整代码:
<template><div><h1>{{ title }}</h1><!-- 3.在template中以标记的语法使用子组件 --><TabMenu></TabMenu><Data></Data></div>
</template><script>
// 1.导入需要的子组件
import TabMenu from '@/components/TabMenu.vue';
import Data from '@/components/Data.vue'
export default {data () {return {title:'我是根组件'}},methods: {},//2.在components的配置项中注册子组件components: {TabMenu,Data}, //TabMenu是另一个子组件,多个子组件用逗号隔开computed: {},watch: {},mounted () {}
}
</script>
<style scoped>
</style>
输出效果:
但是现在里面还没有数据,因为在Data.vue中test是自定义属性
- 接下来在父组件中加入自定义属性:
<Data test="你好啊"></Data>
如果说要在子组件里再定义一个属性,父组件再传一个,只需要在相应位置加上属性后用逗号隔开即可
子组件中:
父组件中:
子传父:自定义事件
recive()
:接收子给父传上来的数据,有参,代表传来的数据
在父组件中:
- 自定义一个事件,这里取名abc
<Data test="你好啊" test1="世界" @abc = "recive"></Data>
- 在methods配置项中定义recive()函数方法
methods: {recive(d){// d:代表子给父发的数据this.title = d //更改title值}},
子组件中:
-
在子组件中编写一个函数,加入一个事件:
-
给v-model的属性tes在data函数的return里面配置一下
-
methods内加上send方法
send(){this.$emit('abc',this.text)//this.$emit('在父组件中配置的事件名字',this.发送给父组件的数据)}
最后输出:
父子组件互传案例
一个App父组件
两个子组件:一个添加待办事项组件、一个待办列表组件
如果之前有项目在终端开着先Ctrl+c关掉
然后新建一个待办项目:vue create todo
,然后依次回车选择配置选项
然后进入到 todo 项目中,删掉HelloWorld.vue文件 和 App.vue中所有代码(输入vue重新生成)
在components文件夹中创建新子组件AddItem.vue 和 List.vue
在父组件中使用子组件:
- 导入需要的子组件
- 在components的配置项中注册子组件
- 在template中以标记的语法使用子组件
目前为止父组件中代码:
<template><div><h1>待办事项</h1><!-- 3.使用 --><AddItem></AddItem><List></List></div>
</template><script>
// 1. 导入
import AddItem from '@/components/AddItem.vue';
import List from '@/components/List.vue';
export default {data () {return {}},methods: {},// 2.注册components: {AddItem,List},computed: {},watch: {},mounted () {}
}
</script>
<style scoped>
</style>
接下来先把List待办列表弄出来再写待办事项,也就是写个父给子的数据传递
增加自定义的属性,使用 v-for 指令对 todolist 进行循环渲染,将 todolist 中的每个元素都显示为一个有序列表中的一条,{{ item }}
则是将前面 item
变量名插入到模板中进行渲染。
由于本组件需要从父组件中接收一个名为 todolist 的属性,所以使用 props
选项来声明了一个具名的 todolist
属性
最后加了点CSS样式
下面是完整的 List.vue 代码:
<template><div><ul><!-- 使用 v-for 指令遍历传入的 todolist 数据,生成 li 列表项 --><li v-for="(item, index) in todolist" :key="index">{{ item }}</li><!-- 2.使用插值语法把上面的自定义名字加上去 --></ul></div>
</template><script>
export default {// 1.定义一个 props 属性,接收父组件传递的 todolist 数据 (自定义的属性)props: ['todolist']
}
</script><style scoped>
/* 为 ul 列表设置样式 */
ul {list-style: none; /* 取消列表项的默认样式 */margin: 0; /* 去除外边距 */padding: 0; /* 去除内边距 */display: flex; /* 将列表项设为弹性项目 */flex-wrap: wrap; /* 当空间不足时,自动换行 */
}/* 为 li 列表项设置样式 */
li {font-size: 1.2rem; /* 设置字体大小 */color: #333; /* 设置字体颜色 */background-color: #f5f5f5; /* 设置背景颜色 */border-radius: 5px; /* 设置圆角 */margin: 0.5rem; /* 设置外边距 */padding: 1rem; /* 设置内边距 */box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1), 0 0 12px rgba(0, 0, 0, 0.1); /* 设置阴影 */text-align: center; /* 设置文本居中 */transition: transform 0.2s cubic-bezier(0, 0, 0.2, 1), box-shadow 0.2s cubic-bezier(0, 0, 0.2, 1); /* 设置过渡效果 */
}/* 当鼠标悬停在 li 列表项上时的样式 */
li:hover {transform: translateY(-5px);box-shadow: 0 12px 24px rgba(0, 0, 0, 0.2), 0 0 12px rgba(0, 0, 0, 0.2);
}
</style>
第一步:在父组件data中把待办事项的数据定义出来
data () {return {items: ['学习','做事','赚钱']// a.把items数据传给list组件去用,用属性todolist去传}},
第二步:用list组件动态绑定items数据
<List :todolist="items"></List>
最后父组件中完整代码:
<template><div><h1>待办事项</h1><!-- 3.使用 --><AddItem></AddItem><!-- b.list组件 加上冒号是动态绑定items数据--><List :todolist="items"></List></div>
</template><script>
// 1. 导入
import AddItem from '@/components/AddItem.vue';
import List from '@/components/List.vue';
export default {data () {return {items: ['学习','做事','赚钱']// a.把items数据传给list组件去用,用属性todolist去传}},methods: {},// 2.注册components: {AddItem,List},computed: {},watch: {},mounted () {}
}
</script>
<style scoped>
</style>
现在打开终端进入该项目路径下启动该项目:npm run serve
启动后运行
接下来是子给父传数据
第一步:加上自定义事件
第二步:放在methods,接受要带参数
<!-- 第一步:自定义事件 -->
<AddItem @item="recive"></AddItem>
...
//中间代码胜率
...methods: {// 第二步:放在methods,接受的话要带参数recive(d){this.items.unshift(d) }},
父组件中完整代码是:
<template><div><h1>待办事项</h1><!-- 3.使用 --><!-- 第一步:自定义事件 --><AddItem @item="recive"></AddItem> <!-- b.list组件 加上冒号是动态绑定items数据--><List :todolist="items"></List></div>
</template><script>
// 1. 导入
import AddItem from '@/components/AddItem.vue';
import List from '@/components/List.vue';
export default {data () {return {items: ['学习','做事','赚钱']// a.把items数据传给list组件去用,用属性todolist去传}},methods: {// 第二步:放在methods,接受的话要带参数recive(d){this.items.unshift(d) }},// 2.注册components: {AddItem,List},computed: {},watch: {},mounted () {}
}
</script>
<style scoped>
</style>
下一步到子组件AddItem.vue里面
1:在里面加一个输入框和按钮
<input type="text" v-model="item"><button @click="send">添加</button>
2:data里面配数据
data () {return {item: ''}},
3:在methods里把数据发送给父组件
methods: {send(){this.$emit('item,this.item')}},
然后在给css内加点样式
最后AddItem.vue完整代码
<template><div class="input-container"> <!-- 输入框容器 --><input type="text" v-model="item" placeholder="输入待办事项" class="input-field"> <!-- 输入框 --><button @click="send" class="add-btn">添加</button> <!-- 添加按钮 --></div>
</template><script>
export default {data () {return {item: '' // 输入框绑定的数据}},methods: {send(){this.$emit('item',this.item) // 发出事件,传递输入框数据}},
}
</script><style scoped>
.input-container { /* 输入框容器样式 */display: flex; /* flex 布局 */align-items: center; /* 垂直居中 */margin-bottom: 20px; /* 底部外边距 */
}.input-field { /* 输入框样式 */border: none; /* 取消边框 */border-bottom: 2px solid #aaa; /* 底部边框 */padding: 0.5rem; /* 内边距 */margin-right: 1rem; /* 右外边距 */font-size: 1rem; /* 字体大小 */font-family: Arial, sans-serif; /* 字体样式 */width: 300px; /* 宽度 */
}.add-btn { /* 添加按钮样式 */background-color: #20A3FF; /* 背景颜色 */border: none; /* 取消边框 */color: white; /* 字体颜色 */padding: 0.5rem; /* 内边距 */border-radius: 5px; /* 圆角 */cursor: pointer; /* 鼠标样式 */transition: all 0.3s ease; /* 过渡效果 */box-shadow: 0 2px 3px rgba(0, 0, 0, 0.3); /* 阴影 */
}.add-btn:hover { /* 鼠标悬停样式 */background-color: #2186e2;transform: translateY(-2px); /* 上移 */box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3); /* 增加阴影 */
}.input-field:focus { /* 输入框获得焦点时的样式 */outline: none; /* 取消选中时的边框 */border-bottom: 2px solid #2186e2; /* 底部边框颜色更改 */
}
</style>
输出效果:
插槽 slot
新建子组件Slot.vue,用vue生成格式后在HTML位置输入
<template><div><h1>我是插槽子组件</h1><!-- 插槽位置 --><slot></slot></div>
</template>
在父组件App.vue中在相应位置进行导入、注册、使用(可以新建一个项目,看起来更直观)
import Slot from '@/components/Slot.vue';components: {Slot},<Slot><h1>你好</h1><!-- 将会显示在子组件的Slot插槽位置上 --></Slot>
运行项目:
多个插槽
通过名字区分
比如在子组件中再加一个slot标签加个名字
<slot name="a"></slot>
在父组件中加上template v-slot:a
<Slot><!-- 将会显示在子组件的Slot插槽位置上 --><h1>你好</h1><!-- 通过名字单独指令子组件的Slot插槽位置 --><template v-slot:a><h2>hello</h2></template></Slot>
另外在css位置加了点样式(可以忽略)
总结
组件化开发总结
Vue组件的基本组成
- template——模版 html代码
- script——脚本 vue配置对象中的各种配置项
- style——样式 css代码
子组件使用的三个步骤
- 在父组件中导入所需子组件
- 在父组件的配置对象中的components配置项中注册子组件
- 在父组件的template中以标记的语法使用子组件
父子组件相互传递数据
-
父传子
a.在子组件配置对象中增加props配置项(自定义属性)
b.在父组件使用子组件时通过自定义的属性名传数据 -
子传父
a.在父组件中增加自定义事件,并编写接受数据的方法 【@item=“recive”】
b.在子组件中增加一个发送数据的方法,调用this.$emit(‘自定义的事件名’,发送的数据)
那么如何在根组件中使用子组件呢?
以App.vue根组件,TabMenu.vue子组件为例:
- 导入需要的子组件(在script标签内)
import TabMenu from '@/components/TabMenu.vue'; //@相当于src
- 在components的配置项中注册子组件
components: {TabMenu},
- 在template中以标记的语法使用子组件
<TabMenu></TabMenu>