antd移动端使用

 安装:

$ npm install --save antd-mobile
# or
$ yarn add antd-mobile
# or
$ pnpm add antd-mobile

 常用组件使用:

 select/picker:

 

 

 

 

import React, { useState } from 'react'
import { Picker, Button, Space, Toast } from 'antd-mobile'
import { DemoBlock, DemoDescription } from './demos-util'
import { basicColumns } from './columns-data'

// 基础用法
function BasicDemo() {
  const [visible, setVisible] = useState(false)
  const [value, setValue] = useState<(string | null)[]>(['M'])
  return (
    <>
      <Button
        onClick={() => {
          setVisible(true)
        }}
      >
        选择
      </Button>
      <Picker
        columns={basicColumns}
        visible={visible}
        onClose={() => {
          setVisible(false)
        }}
        value={value}
        onConfirm={v => {
          setValue(v)
        }}
      />
    </>
  )
}

function ActionsDemo() {
  const [value, setValue] = useState<(string | null)[]>(['M'])
  return (
    <Picker
      columns={basicColumns}
      value={value}
      onConfirm={v => {
        setValue(v)
      }}
    >
      {(_, actions) => <Button onClick={actions.open}>选择</Button>}
    </Picker>
  )
}

// 渲染所选值
function RenderChildrenDemo() {
  const [value, setValue] = useState<(string | null)[]>([])
  return (
    <Picker
      columns={basicColumns}
      value={value}
      onConfirm={setValue}
      onSelect={(val, extend) => {
        console.log('onSelect', val, extend.items)
      }}
    >
      {(items, { open }) => {
        return (
          <Space align='center'>
            <Button onClick={open}>选择</Button>
            {items.every(item => item === null)
              ? '未选择'
              : items.map(item => item?.label ?? '未选择').join(' - ')}
          </Space>
        )
      }}
    </Picker>
  )
}

export default () => {
  return (
    <>
      <DemoBlock title='基础用法'>
        <BasicDemo />
      </DemoBlock>

      <DemoBlock title='渲染所选值'>
        <RenderChildrenDemo />
      </DemoBlock>

      <DemoBlock title='使用 actions 来控制显示/隐藏'>
        <Space direction='vertical' block>
          <ActionsDemo />
          <DemoDescription>
            在 children 渲染函数中,你可以使用第二个参数 actions
            来非常方便的控制 Picker 的显示或隐藏
          </DemoDescription>
        </Space>
      </DemoBlock>

      <DemoBlock title='指令式调用'>
        <Button
          onClick={async () => {
            const value = await Picker.prompt({
              columns: basicColumns,
            })
            Toast.show(`你选择了 ${value}`)
          }}
        >
          弹出 Picker
        </Button>
      </DemoBlock>
    </>
  )
}
export const basicColumns = [
[
{ label: '周一', value: 'Mon' },
{ label: '周二', value: 'Tues' },
{ label: '周三', value: 'Wed' },
{ label: '周四', value: 'Thur' },
{ label: '周五', value: 'Fri' },
],
[
{ label: '上午', value: 'am' },
{ label: '下午', value: 'pm' },
],
]
 

 

 

 

 

 steps:

 

 

 

import React from 'react'
import { Steps } from 'antd-mobile'
import { DemoBlock } from './demos-util'

const { Step } = Steps

export default () => {
  return (
    <>
      <DemoBlock title='横向步骤条'>
        <Steps current={2}>
          <Step 
      title='标题1'
      description='描述'
      style={{
      '--title-font-size': '17px',
      '--description-font-size': '15px',
      '--indicator-margin-right': '12px',
      '--icon-size': '22px',
      }}
    icon={<CheckCircleFill />}
 />
          <Step title='标题2' description='描述' />
          <Step title='标题3' description='描述' />
        </Steps>
      </DemoBlock>

      <DemoBlock title='纵向步骤条'>
        <Steps direction='vertical'>
          <Step title='填写机构信息' status='process' />
          <Step title='签约机构' status='wait' />
          <Step title='关联服务区' status='wait' />
        </Steps>
      </DemoBlock>
    
    </>
  )
}

 

 input:

 

 

import React, { useState } from 'react'
import { Form, Input } from 'antd-mobile'
import { DemoBlock } from 'demos'
import styles from './demo2.less'
import { EyeInvisibleOutline, EyeOutline } from 'antd-mobile-icons'

export default () => {
  const [visible, setVisible] = useState(false)
  return (
    <>
      <DemoBlock title='配合列表使用-水平布局' padding='0'>
        <Form layout='horizontal'>
          <Form.Item label='用户名' name='username'>
            <Input placeholder='请输入用户名' clearable />
          </Form.Item>
          <Form.Item label='密码' name='password'>
            <Input placeholder='请输入密码' clearable type='password' />
          </Form.Item>
        </Form>
      </DemoBlock>

      <DemoBlock title='配合列表使用-竖直布局' padding='0'>
        <Form layout='vertical'>
          <Form.Item label='用户名' name='username'>
            <Input placeholder='请输入用户名' clearable />
          </Form.Item>
          <Form.Item label='密码' name='password'>
            <Input placeholder='请输入密码' clearable type='password' />
          </Form.Item>
        </Form>
      </DemoBlock>

      <DemoBlock title='带辅助操作' padding='0'>
        <Form layout='horizontal'>
          <Form.Item
            label='短信验证码'
            extra={
              <div className={styles.extraPart}>
                <a>发送验证码</a>
              </div>
            }
          >
            <Input placeholder='请输入验证码' clearable />
          </Form.Item>
        </Form>
      </DemoBlock>

      <DemoBlock title='带密码可见' padding='0'>
        <Form layout='horizontal'>
          <Form.Item label='用户名' name='username'>
            <Input placeholder='请输入用户名' clearable />
          </Form.Item>
          <Form.Item
            label='密码'
            name='password'
            extra={
              <div className={styles.eye}>
                {!visible ? (
                  <EyeInvisibleOutline onClick={() => setVisible(true)} />
                ) : (
                  <EyeOutline onClick={() => setVisible(false)} />
                )}
              </div>
            }
          >
            <Input
              placeholder='请输入密码'
              clearable
              type={visible ? 'text' : 'password'}
            />
          </Form.Item>
        </Form>
      </DemoBlock>
    </>
  )
}

 

 

form表单校验:

 

 

import React, { useState, FC } from 'react'
import { Form, Input, Button, Picker, Space } from 'antd-mobile'
import type { PickerValue } from 'antd-mobile/es/components/picker'
import { DownOutline } from 'antd-mobile-icons'

interface MobileValue {
  preValue: string
  realValue: string
}

export default () => {
  const onFinish = (values: any) => {
    console.log(values)
  }

  const checkMobile = (_: any, value: MobileValue) => {
    if (value.realValue) {
      return Promise.resolve()
    }
    return Promise.reject(new Error('手机号不能为空!'))
  }

  return (
    <>
      <Form
        layout='vertical'
        onFinish={onFinish}
        initialValues={{
          mobile: { preValue: '86', realValue: '' },
        }}
        footer={
          <Button block type='submit' color='primary' size='large'>
            提交
          </Button>
        }
      >
        <Form.Header>自定义表单控件</Form.Header>
        <Form.Item
          label='姓名'
          name='name'
          rules={[{ required: true, message: '姓名不能为空!' }]}
        >
          <Input placeholder='请输入姓名' />
        </Form.Item>
        <Form.Item
          label='手机号'
          name='mobile'
          rules={[{ required: true }, { validator: checkMobile }]}
        >
          <MobileField />
        </Form.Item>
      </Form>
    </>
  )
}

const columns = [['86', '01', '02', '03']]

interface MobileFieldProps {
  value?: MobileValue
  onChange?: (value: MobileValue) => void
}

const MobileField: FC<MobileFieldProps> = ({
  value = { preValue: '86', realValue: '' },
  onChange,
}) => {
  const [visible, setVisible] = useState(false)

  const triggerValue = (changedValue: Partial<MobileValue>) => {
    onChange?.({ ...value, ...changedValue })
  }

  const onRealValueChange = (value: string) => {
    triggerValue({ realValue: value })
  }

  const onPreValueChange = (value: PickerValue[]) => {
    const v = value[0]
    if (v === null) return
    triggerValue({ preValue: v })
  }
  return (
    <>
      <Space align='center'>
        <Space align='center' onClick={() => setVisible(true)}>
          <div>+{value.preValue}</div>
          <DownOutline />
        </Space>
        <Input
          placeholder='请输入手机号'
          value={value.realValue}
          onChange={onRealValueChange}
        />
      </Space>
      <Picker
        columns={columns}
        visible={visible}
        onClose={() => {
          setVisible(false)
        }}
        value={[value.preValue]}
        onConfirm={onPreValueChange}
      />
    </>
  )
}

 

 

 

 

 

 

import React from 'react'
import { Form, Input, Button } from 'antd-mobile'
import { AddCircleOutline } from 'antd-mobile-icons'

export default () => {
  const onFinish = (values: any) => {
    console.log(values)
  }

  return (
    <>
      <Form
        onFinish={onFinish}
        initialValues={{
          contacts: [{}],
        }}
        footer={
          <Button block type='submit' color='primary' size='large'>
            提交
          </Button>
        }
        mode='card'
      >
        <Form.Item name={'name'} label='客户名称'>
          <Input placeholder='请输入客户名称' />
        </Form.Item>

        <Form.Array
          name='contacts'
          onAdd={operation => operation.add({ name: '张三' })}
          renderAdd={() => (
            <span>
              <AddCircleOutline /> 添加
            </span>
          )}
          renderHeader={({ index }, { remove }) => (
            <>
              <span>联系人{index + 1}</span>
              <a onClick={() => remove(index)} style={{ float: 'right' }}>
                删除
              </a>
            </>
          )}
        >
          {fields =>
            fields.map(({ index }) => (
              <>
                <Form.Item
                  name={[index, 'name']}
                  label='姓名'
                  rules={[{ required: true, message: '姓名不能为空' }]}
                >
                  <Input placeholder='请输入姓名' />
                </Form.Item>
                <Form.Item name={[index, 'address']} label='地址'>
                  <Input placeholder='请输入地址' />
                </Form.Item>
              </>
            ))
          }
        </Form.Array>
      </Form>
    </>
  )
}

 

 

<Form.Item
  name='birthday'
  label='Birthday'

trigger='onConfirm'

  onClick={(e, datePickerRef: RefObject<DatePickerRef>) => {
    datePickerRef.current?.open() // ⬅️
  }}
>
  <DatePicker>
    {value =>
      value ? dayjs(value).format('YYYY-MM-DD') : 'Please select'
    }
  </DatePicker>
</Form.Item>

 

 

地区联动组件使用:

 

 

import React, { useState } from 'react'
import { Cascader, Button, Space, Toast } from 'antd-mobile'
import { DemoBlock, DemoDescription } from 'demos'

 

import { options, longOptions } from './data'

 

// 基础用法
function BasicDemo() {
const [visible, setVisible] = useState(false)
return (
<>
<Button
onClick={() => {
setVisible(true)
}}
>
选择
</Button>
<Cascader
options={options}
visible={visible}
onClose={() => {
setVisible(false)
}}
/>
</>
)
}

 

// 渲染所选值
function RenderChildrenDemo() {
const [visible, setVisible] = useState(false)
const [value, setValue] = useState<string[]>([])
return (
<Space align='center'>
<Button
onClick={() => {
setVisible(true)
}}
>
选择
</Button>
<Cascader
options={options}
visible={visible}
onClose={() => {
setVisible(false)
}}
value={value}
onConfirm={setValue}
onSelect={(val, extend) => {
console.log('onSelect', val, extend.items)
}}
>
{items => {
if (items.every(item => item === null)) {
return '未选择'
} else {
return items.map(item => item?.label ?? '未选择').join('-')
}
}}
</Cascader>
</Space>
)
}

 

function ActionsDemo() {
const [value, setValue] = useState<string[]>([])
return (
<Cascader
options={options}
value={value}
onConfirm={v => {
setValue(v)
}}
>
{(_, actions) => <Button onClick={actions.open}>选择</Button>}
</Cascader>
)
}

 

export default () => {
return (
<>
<DemoBlock title='基础用法'>
<BasicDemo />
</DemoBlock>

 

<DemoBlock title='渲染所选值'>
<RenderChildrenDemo />
</DemoBlock>

 

<DemoBlock title='指令式调用'>
<Button
onClick={async () => {
const value = await Cascader.prompt({
options,
title: '选择地址',
})
Toast.show(value ? `你选择了 ${value.join('-')}` : '你没有进行选择')
}}
>
弹出 Cascader
</Button>
</DemoBlock>

 

<DemoBlock title='长数据'>
<Button
onClick={async () => {
const value = await Cascader.prompt({
options: longOptions,
placeholder: '请选择',
})
Toast.show(
value ? `你选择了 ${value.join(' - ')}` : '你没有进行选择'
)
}}
>
选择
</Button>
</DemoBlock>

 

<DemoBlock title='使用 actions 来控制显示/隐藏'>
<Space direction='vertical' block>
<ActionsDemo />
<DemoDescription>
在 children 渲染函数中,你可以使用第二个参数 actions
来非常方便的控制 Picker 的显示或隐藏
</DemoDescription>
</Space>
</DemoBlock>
</>
)
}

 

 

 数据结构:

 

 

 

posted @ 2022-12-03 17:15  忘忧谷的孟婆汤  阅读(1023)  评论(0)    收藏  举报