展示类组件封装

当属性的绘制完全依赖属性时,封装变得非常容易:

function Button({style, text} : {style : any, text : string}){return <button style={style}>text</button>
}

容器类组件

如果一个组件是容器,`vue` 是通过slot来处理的。

const ButtonWithSlots = (_ : any, context : any) => {return <button>{context.slots.default()}</button>
}

在`@vue/babel-plugin-jsx`中,slots被封装到了渲染函数的第二个参数中。 `slots.default` 代表了默认的`slot` 。使用时:

export const ButtonExample02 = () => {return <ButtonWithSlots><span>你好!</span></ButtonWithSlots>
}

当然可以有多个`slot` ,不过建议不要这样,因为这样阅读起来不是非常方便(美观):

const A = (props, { slots }) => (<><h1>{ slots.default ? slots.default() : 'foo' }</h1><h2>{ slots.bar?.() }</h2></>
);const App = {setup() {const slots = {bar: () => <span>B</span>,};return () => (<A v-slots={slots}><div>A</div></A>);},
};// orconst App = {setup() {const slots = {default: () => <div>A</div>,bar: () => <span>B</span>,};return () => <A v-slots={slots} />;},
};// or you can use object slots when `enableObjectSlots` is not false.
const App = {setup() {return () => (<><A>{{default: () => <div>A</div>,bar: () => <span>B</span>,}}</A><B>{() => "foo"}</B></>);},
};

输入组件

vue Input表单的一个完整的例子

import { ref, defineComponent, PropType, watch } from "vue"const Input = defineComponent({props: {onChange: {type: Function as PropType<(v: any) => void>,required: false,},value: {type: String,required: false,},},setup(props) {const input = ref<HTMLInputElement | null>(null)watch(() => props.value,() => {const ipt = input.value!if(ipt.value !== props.value) {ipt.value = props.value || ""}})return () => {return (<input onInput={e => {props.onChange &&props.onChange((e.target as HTMLInputElement).value)}} value={props.value} ref={input} />)}},
})export const FormExample = defineComponent({setup(){let formData = {username : '张三',info : "xxx"}const ver = ref(0)return () => {return <div key={ver.value}><button onClick={() => {console.log(formData)formData = {username : '张三',info : "xxx"}ver.value ++}}>重置/提交</button><Inputvalue={formData.username}onChange={(v) => formData.username = v}/><Inputvalue={formData.info}onChange={(v) => formData.info = v}/></div>}}})

对表单数据的封装

可以对表单数据进行一定的封装,使用起来更加方便:

import {ref,defineComponent,PropType,watch,
} from "vue"import {Input} from '../components/Input'
import {useForm} from '../hooks/useForm'export const FromExample02 = defineComponent({setup() {const {form, ver} = useForm({username: "张三",info: "xxx",})watch(form.getValues(), () => {console.log('form data changed', form.getValues().value)})return () => (<div><buttononClick={() => {const values = form.getValues().valueconsole.log("submit", values)form.setValues({username: "张三",info: "xxx",})ver.value++}}>提交/重置</button><Input{...form.username}/><Input{...form.info}/></div>)},
})

封装公共行为

封装事件和计算

function useMouse() {const x = ref(0)const y = ref(0)function handler(e: MouseEvent) {x.value = e.xy.value = e.yconsole.log('move', e.x, e.y)}window.addEventListener("mousemove", handler)onScopeDispose(() => {window.removeEventListener("mousemove", handler)})return { x, y }
}

公共Scroll事件的封装

封装一个滚动到底部的判定

import { defineComponent } from "vue"class ScrollDescriptor {private left: number = 0private top: number = 0private scrollHeight: number = 0private offsetHeight: number = 0private scrollToBottomHandlers: Function[] = []public onScrollToBottom(handler: Function) {this.scrollToBottomHandlers.push(handler)return () => {this.scrollToBottomHandlers =this.scrollToBottomHandlers.filter((x) => x !== handler)}}private triggerScrollToBottom() {this.scrollToBottomHandlers.forEach((h) => h())}public update(left: number,top: number,offsetHeight: number,scrollHeight: number) {this.left = leftthis.top = topthis.scrollHeight = scrollHeightthis.offsetHeight = offsetHeightif (this.bottomReached()) {this.triggerScrollToBottom()}}public bottomReached() {return this.top + this.offsetHeight >= this.scrollHeight}
}const useScroll = () => {const scrollInfo = new ScrollDescriptor()const scrollHandler = <T extends HTMLElement>(e: Event) => {const scroller = e.currentTarget as Tconst left = scroller.scrollLeftconst top = scroller.scrollTopscrollInfo.update(left,top,scroller.offsetHeight,scroller.scrollHeight)}return {onScroll: scrollHandler,info: scrollInfo,}
}export const ScrollerExample = defineComponent({setup() {const { onScroll, info } = useScroll()info.onScrollToBottom(() => {console.log('here---')})return () => (<divonScroll={onScroll}style={{height: '600px',width: '400px',overflow: "scroll",}}><divstyle={{height: '800px',width: "100%",background: "red",}}></div><divstyle={{height: '800px',width: "100%",background: "blue",}}></div><divstyle={{height: '800px',width: "100%",background: "yellow",}}></div></div>)},
})

封装请求和逻辑

import {ref, defineComponent} from 'vue'
import Mock from 'mockjs'type Product = {name : string
}
function useProducts() {const list = ref<Product[] | null>(null)async function request() {list.value = Mock.mock({"array|1-10" : [{name: /iphone|xiaomi|hongmi|huawei|sanxing|google|ms/,}],}).arrayconsole.log(list.value)}request()return {list,reload: request,}
}export const ProductList = defineComponent({setup() {const {list, reload} = useProducts()return () => {return <div><button onClick={reload}>reload</button><ul>{list.value?.map( (x, i) => {return <li key={i}>{x.name}</li>})}</ul></div>}}})

1

2-3-7 Vue3 组件封装相关推荐

  1. element-plus的el-icon和@element-plus/icons vue3 组件封装与使用

    使用 element-plus 时发现了一个问题:icon 需要单独安装和引入,让我很是难受,官网是这么说的(大概意思如下): $ yarn add @element-plus/icons # 或者 ...

  2. 【vue3组件封装】Icon图标组件

    使用 <s-icon icon="icon-file"/> 准备图标 这里使用的icon均自于https://www.iconfont.cn/,它是支持unicode. ...

  3. vue3 - 仿 element-ui Breadcrumb 面包屑组件封装自己的面包屑组件

    仿 element-ui Breadcrumb 面包屑组件封装自己的面包屑组件 element-ui 面包屑结构 <el-breadcrumb separator="/"&g ...

  4. Vue3 element-ui实现Pagination分页组件--封装分页

    什么是Pagination分页组件? 在 B 端的 web 开发中,分页组件或者叫分页器,是较为常用的控件之一,通常配合表格或列表,实现数据量大的情况下,分页拆解数据的功能. 1.scrollTo和滚 ...

  5. vue3使用jodit富文本编辑器,自定义各项配置及组件封装

    目录 常用配置 设置中文 字体设置 CDN的引用 图片上传 对编辑器中生成的元素添加默认属性 组件封装 本文使用时的版本: "vue": "^3.2.36", ...

  6. vue2+webpack/vue3+vite 封装svg组件总结笔记

    一.vue2+webpack 1.npm安装依赖包 npm i svg-sprite-loader package.json "svg-sprite-loader": " ...

  7. vue3中,echarts使用(四)02——柱状图之堆叠条形图-定制化 封装切换tag标签组件 封装title组件

    vue3中,echarts使用(四)02--柱状图之堆叠条形图-定制化 & 封装切换tag标签组件 & 封装title组件 效果 代码 1.主页面 index.vue <temp ...

  8. Vue3VideoPlay+vue3+ts封装一个视频播放组件

    vue3+ts封装一个视频播放组件 基于Vue3VideoPlay 做了常用的配置,复制即用! 官方文档https://codelife.cc/vue3-video-play/ 安装 npm安装: n ...

  9. 2.vue3医疗在线问诊项目 - _登录模块 ==> 代码片段、css变量主题定制、cp-nav-bar组件封装、svg打包精灵图插件、cp-icon组件封装、表单校验、密码登录、短信验证码登录及两者

    2.医疗在线问诊项目 - _登录模块 ==> 代码片段.css变量主题定制.cp-nav-bar组件封装.svg打包精灵图插件.cp-icon组件封装.表单校验.密码登录.短信验证码登录及两者的 ...

最新文章

  1. ubuntu在系统启动logo过后无法进入桌面的处理方法
  2. CF572_Div2_D2
  3. VS2008如何添加 OLE/COM 对象查看器 .
  4. vue检测不到data里数组里面元素的变化
  5. 前后端分离架构一直没机会实战?1周完成Vue+Core WebApi移动商城实战(含源码)!...
  6. Uva 11178 Morley定理
  7. ftp上传乱码_ftp同步图片到本地文件夹,ftp同步图片到本地文件夹的实现步骤
  8. 智慧机场大数据可视化分析决策系统
  9. BUUCTF刷题-RAR 压缩包暴力破解密码
  10. 职场泥潭 | 这样的IT公司绝对不宜久留
  11. Genesys Business Continuity 部署
  12. MySQL 常见的 9 种优化方法
  13. Android Studio出现APP闪退问题(My Application keeps stopping)
  14. 鼠标每隔几秒失去焦点,鼠标每隔几秒转圈,鼠标每隔几秒刷新
  15. dxc 5.0 多线程同步
  16. 选定关键词爬取智联招聘职位概览信息
  17. 秋招春招,网申在线测评中的智力测试
  18. 【功能安全】【AutoSAR】程序流监控机制
  19. 自己动手修改用友致远OA2.75的问题
  20. 女生应该找一个会打DOTA有会玩ACM的男生当老公

热门文章

  1. LoadRunner编写Socket协议脚本方法
  2. Python exec函数用法
  3. 听韩顺平聊PHP初学者如何变身大牛(二)
  4. IP175G交换机原理图
  5. redis多路IO复用原理
  6. 时间日期格式化的两种方式
  7. MFC界面库BCGControlBar的介绍
  8. uniapp 之 扫普通二维码进入小程序
  9. 云服务器存储扩容详解
  10. js 汉字转化拼音