2-3-7 Vue3 组件封装
Posted 沿着路走到底
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2-3-7 Vue3 组件封装相关的知识,希望对你有一定的参考价值。
展示类组件封装
当属性的绘制完全依赖属性时,封装变得非常容易:
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>
);
,
;
// or
const 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>
<Input
value=formData.username
onChange=(v) => formData.username = v
/>
<Input
value=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>
<button
onClick=() =>
const values = form.getValues().value
console.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.x
y.value = e.y
console.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 = 0
private top: number = 0
private scrollHeight: number = 0
private offsetHeight: number = 0
private 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 = left
this.top = top
this.scrollHeight = scrollHeight
this.offsetHeight = offsetHeight
if (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 T
const left = scroller.scrollLeft
const top = scroller.scrollTop
scrollInfo.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 () => (
<div
onScroll=onScroll
style=
height: '600px',
width: '400px',
overflow: "scroll",
>
<div
style=
height: '800px',
width: "100%",
background: "red",
></div>
<div
style=
height: '800px',
width: "100%",
background: "blue",
></div>
<div
style=
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/,
],
).array
console.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 组件封装的主要内容,如果未能解决你的问题,请参考以下文章