赞
踩
当属性的绘制完全依赖属性时,封装变得非常容易:
- 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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。