vue3学习11、12、13组件化开发(vue组件化开发案例)
ztj100 2024-11-12 14:22 43 浏览 0 评论
利用vue脚手架创建一个项目
vue create component_demo
可以在vscode中安装Vue VSCode Snippets插件或vue3 snippets,帮助生成一些代码片段
vbase-css
可以快速生成vue3模板
组件通信
父子组件之间通信
- 父组件传递给子组件:通过props属性
- 子组件传递给父组件:通过$emit触发事件
在父组件中引入组件传值
<show-message :title="title"></show-message>
子组件中在props中定义
props: {
title: {
type: String,
require: true, //表示这个属性是必传的
default: '123' //默认属性
},
//当属性是Object型时,默认值要为一个函数.因为多个组件会引用同一个对象
info: {
type: Object,
default() {
return {name: 'juju'}
}
},
//自定义验证函数
man: {
validator(value) {
//这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].include(value)
}
}
}
props命名 建议父组件中要传递的值采用驼峰写法
<show-message :message-info="title"></show-message>
...
data() {
return {
messageInfo: 'damn'
}
}
非props的Attribute
当我们传递给一个组件某个属性,但是该属性并没有定义对应的props或者emits,就称之为非props的Aaaribute
常见的包括css,style,id属性等 例如当给子组件设置一个class属性
<show-message class="liin" :title="title"></show-message>
当组件有单个根节点时,会自动添加到根节点的attribute
<template>
<div class="liin">
<h2>{{ title }}</h2>
<h2>{{ info.name }}</h2>
</div>
</template>
如果我们不希望根组件继承attribute,可以在子组件中设置inheritAttrs: false 我们可以通过$attrs来访问所有的非props的attribute
<h2 :class="$attrs.class">{{ title }}</h2>
通过v-bind绑定所有属性 父组件
<show-message id="xixi" class="liin" :title="title"></show-message>
子组件
<h2 v-bind="$attrs">{{ title }}</h2>
子组件传递给父组件 子组件中与vue2不同的是多了个emit参数,里面存放着可能要触发的事件
export default {
//emits属性,里面存放着待会会触发的事件
emits: ["add", "sub"],
//emits的对象写法,目的是为了进行参数的验证
emits: {
sub: null,
add: (name, age) => {
if(name == 'juju') {
return true
}
return false
}
},
methods: {
increament() {
this.$emit("add","juju",18) //后面多个参数跟着的是要传的参数
},
decreament() {
this.$emit("sub")
},
}
}
父组件中写法与vue2相同
<counter-operation @add="addOne" @sub="subOne"></counter-operation>
非父组件的通信
- provide/inject
- mitt全局事件总线
- vuex
provide和inject
无论层级结构有多深,父组件都可以作为其所有子组件的依赖提供者; 父组件有一个provide选项来提供数据,子组件有一个inject选项来使用这些数据
在父组件中添加一个provide
components: {
Home
},
provide: {
name: 'juju',
age: 18
},
在子孙组件中注入
export default {
inject: ["name", "age"]
}
当然,许多情况下数据都要从data中拿并从后台请求了,此时的provide要写成函数形式
provide() {
return {
name: juju,
age: 18,
title: this.title
}
},
如果后续title改变的话,inject里的值并不是响应式的,可以使用vue中的computed函数
import {computed} from 'vue'
provide() {
return {
name: juju,
age: 18,
title: computed(() => {
this.title
})
}
},
全局事件总线mitt库
安装mitt库
npm install mitt
创建一个eventbus.js文件
import mitt from 'mitt'
const emitter = mitt();
export default emitter;
// 也可以创建多个mitt对象
测试叔侄组件之间通信 在叔组件中传递
import emmiter from '../util/eventbus.js'
methods: {
btnClick() {
emmiter.emit("handle", "juju",18); //第一个参数方法名,后面跟着的是参数
}
}
在侄组件的生命周期中监听
import emitter from '../util/eventbus.js'
created() {
emitter.on("handle", (name,age)=> {
console.log(name)
})
}
mitt事件取消
emitter.all.clear(); //全部取消监听
function onFoo(){}
emitter.on('foo', onFoo) //监听
emitter.off('foo', onFoo) //取消监听
插槽slot
对于不同的区域可能存放不同的内容,因此要使用slot
- 插槽的使用过程其实是抽取共性,预留不同
- 我们会将共同的元素,内容依然在组件内进行封装
- 同时将不同的元素使用slot作为占位,让外部决定到底显示什么样的元素
简单插槽的使用
定义一个子组件
<h2>组件开始</h2>
<slot></slot>
<h2>组件结束</h2>
在父组件中使用
<my-slot-cpn>
<button>我是按钮</button>
</my-slot-cpn>
此时中间部分可以展示按钮或者图片或者组件,vue会将内容替换到slot的位置
具名插槽的使用
插槽的默认使用 如果子组件是这样的
<div>
<h2>组件开始</h2>
<slot>
<i>我是默认内容</i>
</slot>
<h2>组件结束</h2>
</div>
父组件
<my-slot-cpn>
</my-slot-cpn>
则显示默认内容
具名插槽
在子组件中编写有name属性的插槽
<template>
<div class="nav-bar">
<div class="left">
<slot name="left"></slot>
</div>
<div class="center">
<slot name="center"></slot>
</div>
<div class="right">
<slot name="right"></slot>
</div>
</div>
</template>
在父组件中用template v-slot方式分配元素至对于的slot内
<!-- 具名插槽的使用 -->
<nar-bar>
<template v-slot:left>
<button>左边按钮</button>
</template>
//等价于
<template #left>
<button>左边按钮</button>
</template>
<template v-slot:center>
<h2>我是标题</h2>
</template>
<template v-slot:right>
<i>右边的元素</i>
</template>
</nar-bar>
效果
如果名字是不定的话,template应该这么写
<template v-slot:[name]>
<i>右边的元素</i>
</template>
作用域插槽
即子组件中的slot属性,可以传给父组件 子组件
<template>
<div>
<template v-for="(item,index) in names" :key="item">
<slot :item="item" :index="index"></slot>
</template>
</div>
</template>
父组件通过v-slot取得
<show-names>
<template v-slot="slotProps">
<button>{{slotProps.item}}-{{ slotProps.index }}</button>
</template>
</show-names>
//是下面的简写,v-slot后跟插槽名字
<show-names>
<template v-slot:default="slotProps">
<button>{{slotProps.item}}-{{ slotProps.index }}</button>
</template>
</show-names>
当只有默认插槽时,可以使用独占默认插槽写法
<show-names v-slot="slotProps">
<button>{{slotProps.item}}-{{ slotProps.index }}</button>
</show-names>
动态组件的实现
根据不同的场景,去渲染不同的组件。以前基本都使用v-if去判断从而渲染不同的组件。但是当组件很多的时候,组件会显得很臃肿。此时可以考虑采用动态组件去实现。
动态组件是使用component组件,通过特殊的attribute is来实现。 例如
<component is="hello-world"></component>
此时就会渲染HelloWorld组件
动态组件传递参数
<component is="hello-world" name="juju" :age="18" @helloClick="handleClick"></component>
此时在helloworld组件可以用props接收,同时动态组件可以接受子组件的点击事件
keep-alive
默认情况下,切换组件会被销毁,再次回来会重新创建组件。此时,在开发中某些情况我们希望继续保持组件的状态,而不是销毁掉,这时我们可以使用一个内置组件:keep-alive。
<keep-alive>
<component is="hello-world" name="juju" :age="18" @helloClick="handleClick"></component>
<keep-alive>
keep-alive有一些属性,
- include.[string|regexp|array]只有名称匹配的组件会被缓存。
- exclude[string|regexp|array]任何匹配的组件都不会会被缓存。
- max[number|string]最多可以缓存多少组件实例,一旦达到这个数字,那么缓存组件中最近没有被访问的实例会被销毁
include是根据组件的name属性来进行适配,因此有时需要给组件加上name属性
export default {
name: 'about',
}
webpack分包
正常打包的话会将所有资源打包到一个app.js文件中,采用webpack分包方式会将利用分包的资源打包到一个chunk文件中,需要时再去加载,可以优化首屏渲染。
//通过import函数导如的模块,后续webpack对其进行打包的时候就会进行分包的操作
import('./utils/math').then(res => {console.log(sum(10,20))})
异步组件
同时vue3提供一个函数可以使打包后的组件成为一个单独的文件夹,加快首屏渲染速度 defineAsyncComponent接受两种类型的参数: 类型一:工厂函数,该工厂函数需要返回一个promise对象 类型二:接受一个对象类型,对异步函数进行配置
import {defineAsyncComponent} from 'vue'
const AsyncHello = defineAsyncComponent(() => import('./components/HelloWorld.vue'))
一般开发中使用路由懒加载比较多
获取元素和refs
在某些情况下,我们组件想要直接获取到元素对象或者子组件实例 在vue开发中我们不推荐dom操作的,这个时候,可以给元素或者组件绑定以恶搞ref的attribute属性
<h2 ref="title">哈哈哈哈哈哈</h2>
mounted() {
console.log(this.$refs.title)
},
打印结果
对于组件来说,调用this.refs.xx可以获取组件实例,取得data中的数据或调用一些方法。 同时,可以在子组件中采用this.parent取得父组件实例以及parent取得父组件实例以及parent取得父组件实例以及root获取根组件
组件的生命周期
- beforecreated
- created
- beforemounted
- mounted
- beforeUpdate
- updated
- beforeUnmount
- unmounted
对于有缓存的组件来说,再次进入时,我们是不会执行created或者mounted等生命周期的,这时我们可以使用activated和deactiveated这两个生命周期钩子函数来监听。
组件的v-model
//组件绑定v-model与下列的等价
<hy-input v-model="title"></hy-input>
<!-- <hy-input :modelValue="title" @update:model-value="title = $event"></hy-input> -->
<template>
<div>
<button @click="btnClick">input按钮</button>
{{ modelValue }}
</div>
</template>
<script>
export default {
props: {
modelValue: String
},
emits: ["update:modelValue"],
methods: {
btnClick() {
this.$emit("update:modelValue", '嘿嘿')
}
}
}
</script>
$event为update:model-value事件传出来的参数
如果子组件中有input可以实现v-model绑定计算属性的操作,因为不能绑定到props里
<input v-model="value" />
...
computed: {
value: {
get(){
return this.modelValue
},
set(value) {
this.$emit("update:modelValue", value)
}
}
},
绑定多个v-model,后面加名字,此时why为子组件prop的值
<hy-input v-model="title" v-model:why="why"></hy-input>
相关推荐
- sharding-jdbc实现`分库分表`与`读写分离`
-
一、前言本文将基于以下环境整合...
- 三分钟了解mysql中主键、外键、非空、唯一、默认约束是什么
-
在数据库中,数据表是数据库中最重要、最基本的操作对象,是数据存储的基本单位。数据表被定义为列的集合,数据在表中是按照行和列的格式来存储的。每一行代表一条唯一的记录,每一列代表记录中的一个域。...
- MySQL8行级锁_mysql如何加行级锁
-
MySQL8行级锁版本:8.0.34基本概念...
- mysql使用小技巧_mysql使用入门
-
1、MySQL中有许多很实用的函数,好好利用它们可以省去很多时间:group_concat()将取到的值用逗号连接,可以这么用:selectgroup_concat(distinctid)fr...
- MySQL/MariaDB中如何支持全部的Unicode?
-
永远不要在MySQL中使用utf8,并且始终使用utf8mb4。utf8mb4介绍MySQL/MariaDB中,utf8字符集并不是对Unicode的真正实现,即不是真正的UTF-8编码,因...
- 聊聊 MySQL Server 可执行注释,你懂了吗?
-
前言MySQLServer当前支持如下3种注释风格:...
- MySQL系列-源码编译安装(v5.7.34)
-
一、系统环境要求...
- MySQL的锁就锁住我啦!与腾讯大佬的技术交谈,是我小看它了
-
对酒当歌,人生几何!朝朝暮暮,唯有己脱。苦苦寻觅找工作之间,殊不知今日之事乃我心之痛,难道是我不配拥有工作嘛。自面试后他所谓的等待都过去一段时日,可惜在下京东上的小金库都要见低啦。每每想到不由心中一...
- MySQL字符问题_mysql中字符串的位置
-
中文写入乱码问题:我输入的中文编码是urf8的,建的库是urf8的,但是插入mysql总是乱码,一堆"???????????????????????"我用的是ibatis,终于找到原因了,我是这么解决...
- 深圳尚学堂:mysql基本sql语句大全(三)
-
数据开发-经典1.按姓氏笔画排序:Select*FromTableNameOrderByCustomerNameCollateChinese_PRC_Stroke_ci_as//从少...
- MySQL进行行级锁的?一会next-key锁,一会间隙锁,一会记录锁?
-
大家好,是不是很多人都对MySQL加行级锁的规则搞的迷迷糊糊,一会是next-key锁,一会是间隙锁,一会又是记录锁。坦白说,确实还挺复杂的,但是好在我找点了点规律,也知道如何如何用命令分析加...
- 一文讲清怎么利用Python Django实现Excel数据表的导入导出功能
-
摘要:Python作为一门简单易学且功能强大的编程语言,广受程序员、数据分析师和AI工程师的青睐。本文系统讲解了如何使用Python的Django框架结合openpyxl库实现Excel...
- 用DataX实现两个MySQL实例间的数据同步
-
DataXDataX使用Java实现。如果可以实现数据库实例之间准实时的...
- MySQL数据库知识_mysql数据库基础知识
-
MySQL是一种关系型数据库管理系统;那废话不多说,直接上自己以前学习整理文档:查看数据库命令:(1).查看存储过程状态:showprocedurestatus;(2).显示系统变量:show...
- 如何为MySQL中的JSON字段设置索引
-
背景MySQL在2015年中发布的5.7.8版本中首次引入了JSON数据类型。自此,它成了一种逃离严格列定义的方式,可以存储各种形状和大小的JSON文档,例如审计日志、配置信息、第三方数据包、用户自定...
你 发表评论:
欢迎- 一周热门
-
-
MySQL中这14个小玩意,让人眼前一亮!
-
旗舰机新标杆 OPPO Find X2系列正式发布 售价5499元起
-
【VueTorrent】一款吊炸天的qBittorrent主题,人人都可用
-
面试官:使用int类型做加减操作,是线程安全吗
-
C++编程知识:ToString()字符串转换你用正确了吗?
-
【Spring Boot】WebSocket 的 6 种集成方式
-
PyTorch 深度学习实战(26):多目标强化学习Multi-Objective RL
-
pytorch中的 scatter_()函数使用和详解
-
与 Java 17 相比,Java 21 究竟有多快?
-
基于TensorRT_LLM的大模型推理加速与OpenAI兼容服务优化
-
- 最近发表
- 标签列表
-
- idea eval reset (50)
- vue dispatch (70)
- update canceled (42)
- order by asc (53)
- spring gateway (67)
- 简单代码编程 贪吃蛇 (40)
- transforms.resize (33)
- redisson trylock (35)
- 卸载node (35)
- np.reshape (33)
- torch.arange (34)
- npm 源 (35)
- vue3 deep (35)
- win10 ssh (35)
- vue foreach (34)
- idea设置编码为utf8 (35)
- vue 数组添加元素 (34)
- std find (34)
- tablefield注解用途 (35)
- python str转json (34)
- java websocket客户端 (34)
- tensor.view (34)
- java jackson (34)
- vmware17pro最新密钥 (34)
- mysql单表最大数据量 (35)