php中文网

React Native 的基本级联形式

php中文网

我想分享我处理级联表单字段的 3 种方法。

  1. 第一种方法是通用的,使用状态变量。
  2. 第二种是使用普通变量和一个布尔状态变量来触发状态效果(刷新页面)。
  3. 第三种是带有普通变量的动态表单字段。

在这篇文章中,我们看到第一种方法,即基于国家、州、城市数据处理级联表单字段的常用方法。

套餐

react-native-element-dropdown
react-native-paper

我们正在使用react-native-element-dropdown作为下拉字段

基页


import react, { usestate, useeffect } from "react";
import { view, text, stylesheet, touchableopacity } from "react-native";
import { dropdown } from "react-native-element-dropdown";

export default function app() {
  return (
    <view style={styles.container}>
      <view>
        <text>country</text>
        <zdropdown
          data={[]}
          labelfield=""
          valuefield=""
          value={null}
          isfocus={false}
          onchange={null}
        />
        <text>state</text>        
        <zdropdown
          data={[]}
          labelfield=""
          valuefield=""
          value={null}
          isfocus={false}
          onchange={null}      
        />
        <text>city</text>
        <zdropdown
          data={[]}
          labelfield=""
          valuefield=""
          value={null}
          isfocus={false}
          onchange={null}      
        />
      </view>
      <view>
        <text>selected country</text>
        <text style={styles.selectedvalue}>{country.selectedcountry.name}</text>
        <text>selected state</text>
        <text style={styles.selectedvalue}>{state.selectedstate.name}</text>
        <text>selected city</text>
        <text style={styles.selectedvalue}>{city.selectedcity.name}</text>
      </view>
      <touchableopacity onpress={null} style={styles.clrbtn}>
        <text style={styles.clrbtntxt}>reset</text>
      </touchableopacity>
    </view>
  );
}

const zdropdown = ({
  data,
  labelfield,
  valuefield,
  value,
  onfocus,
  onblur,
  onchange,
  isfocus,
}) => {
  return (
    <dropdown
      mode={"auto"}
      style={[styles.dropdown, isfocus ? { bordercolor: "dodgerblue" } : {}]}
      placeholderstyle={styles.placeholderstyle}
      selectedtextstyle={styles.selectedtextstyle}
      inputsearchstyle={styles.inputsearchstyle}
      iconstyle={styles.iconstyle}
      search={data.length > 5}
      maxheight={300}
      searchplaceholder="search..."
      data={data}
      labelfield={labelfield}
      valuefield={valuefield}
      placeholder={!isfocus ? "select item" : "..."}
      value={value}
      onfocus={onfocus}
      onblur={onblur}
      onchange={onchange}
    />
  );
};

const styles = stylesheet.create({
// style props
});

zdropdown 是一个自定义组件。

样本数据

const listcountry = [
  { countryid: "1", name: "india" },
  { countryid: "2", name: "uk" },
  { countryid: "3", name: "canada" },
  { countryid: "4", name: "us" },
];

const listsate = [
  { stateid: "1", countryid: "1", name: "state1_india" },
  { stateid: "4", countryid: "2", name: "state1_uk" },
  { stateid: "7", countryid: "3", name: "state1_canada" },
  { stateid: "10", countryid: "4", name: "state1_us" },
];

const listcity = [
  {
    cityid: "1",
    stateid: "1",
    countryid: "1",
    name: "city1_state1_country1",
  },
   {
    cityid: "6",
    stateid: "2",
    countryid: "1",
    name: "city6_state2_country1",
  },
  {
    cityid: "7",
    stateid: "3",
    countryid: "1",
    name: "city7_state3_country1",
  }, 
  {
    cityid: "23",
    stateid: "8",
    countryid: "3",
    name: "city23_state8_country3",
  }, 
  {
    cityid: "30",
    stateid: "10",
    countryid: "4",
    name: "city30_state10_country4",
  }, 
  {
    cityid: "35",
    stateid: "12",
    countryid: "4",
    name: "city35_state12_country4",
  },
  {
    cityid: "36",
    stateid: "12",
    countryid: "4",
    name: "city36_state12_country4",
  },
];

表单变量

我们使用 4 个状态变量,其中 3 个用于表单字段,其余一个用于触发焦点效果。

export default function app() {
  const [country, setcountry] = usestate({
    data: [],
    selectedcountry: {},
    value: null,
  });
  const [state, setstate] = usestate({
    data: [],
    selectedstate: {},
    value: null,
  });
  const [city, setcity] = usestate({ data: [], selectedcity: {}, value: null });

  const [ddfocus, setddfocus] = usestate({
    country: false,
    state: false,
    city: false,
  });

  return (
    <view style={styles.container}>
      <view>
        <text>country</text>
        <zdropdown
          data={country.data}
          labelfield="name"
          valuefield="countryid"
          value={country.value}
          isfocus={ddfocus.country}
          onchange={null}
        />
        <text>state</text>
        <zdropdown
          data={state.data}
          labelfield="name"
          valuefield="stateid"
          value={state.value}
          isfocus={ddfocus.state}
          onchange={null}
        />
        <text>city</text>
        <zdropdown
          data={city.data}
          labelfield="name"
          valuefield="cityid"
          value={city.value}
          isfocus={ddfocus.city}
          onchange={null}
        />
      </view>
      . . .
    </view>
  );
}

焦点和模糊事件比 onchange 事件更容易被触发,因此对于焦点更改,这里使用一个单独的状态变量,以免弄乱下拉数据更改。

负载国家

从示例数据中加载国家/地区下拉列表。 (可以使用api调用)

export default function app() {
. . .
  const loadcountry = () => {
    // load data from api call
    setcountry({ data: [...listcountry], selectedcountry: {}, value: null });
  };

  useeffect(() => {
    loadcountry();
  }, []);

return (
. . .
)

对焦/模糊

当选择一个下拉菜单时,该字段必须被聚焦,而其余字段应该被模糊。我们正在使用一个函数来处理这个问题。

  const focusfield = (fld = '') => {
    const obj = { country: false, state: false, city: false };
    if (fld) obj[fld] = true;
    setddfocus(obj);
  };
        <text>country</text>
        <zdropdown
          . . .
          isfocus={ddfocus.country}
          onfocus={() => focusfield('country')}
          onblur={() => focusfield('')}
          onchange={null}
        />
        <text>state</text>
        <zdropdown
        . . .
          isfocus={ddfocus.state}
          onfocus={() => focusfield('state')}
          onblur={() => focusfield('')}
          onchange={null}
        />
        <text>city</text>
        <zdropdown        
        . . .
          isfocus={ddfocus.city}
          onfocus={() => focusfield('city')}
          onblur={() => focusfield('')}
          onchange={null}       
        />

我们现在已经完成了一半。

加载状态状态

在选择的国家/地区,我们需要根据所选国家/地区加载相应的 states。

更新国家/地区字段,根据国家/地区选择加载州并关注国家/地区。

  <text>country</text>
  <zdropdown
    . . .
    onchange={(item) => {
      setcountry({
        ...country,
        selectedcountry: item,
        value: item.countryid,
      });
      loadstate(item.countryid);
      focusfield("");
    }}
  />

当国家/地区发生变化时,州和城市都会发生变化。因此,在设置新值之前,我们需要清除现有数据。

const loadstate = async (cntid) => {
  // load data from api call
  setstate({ data: [], selectedstate: {}, value: null });
  setcity({ data: [], selectedcity: {}, value: null });
  const arr = listsate.filter((ele) => ele.countryid === cntid);
  setstate({ ...state, data: [...arr] });
  console.log("respective states ", arr);
};

负载城市

并根据选择加载城市字段。

    <text>state</text>
    <zdropdown
      . . .
      onchange={(item) => {
        setstate({ ...state, selectedstate: item, value: item.stateid });
        loadcity(item.stateid);
        focusfield("");
      }}
     />
const loadcity = async (stid) => {
  // load data from api call
  setcity({ data: [], selectedcity: {}, value: null });
  const arr = listcity.filter((ele) => ele.stateid === stid);
  setcity({ ...city, data: [...arr] });
};

一切就绪,表单字段现在可以正常工作了。

如果我们再处理 2 个附加功能,我们就完成了。一种是休息页面,另一种是验证表单并显示警告。

重置页面

表单变量和焦点变量应该被清除。

. . .
const resetform = () => {
  focusfield("");
  setcountry({ data: [...listcountry], selectedcountry: {}, value: null });
  setstate({ data: [], selectedstate: {}, value: null });
  setcity({ data: [], selectedcity: {}, value: null });
};
. . .

  <touchableopacity onpress={() => resetform()} style={styles.clrbtn}>
    <text style={styles.clrbtntxt}>reset</text>
  </touchableopacity>
. . .

警告

如果父字段值为空,我们必须显示警告消息。为此,我们使用 paper 中的 snackbar 组件。

import { snackbar } from "react-native-paper";

export default function app() {
  . . .
  const [visible, setvisible] = usestate(false);
  const [snackmsg, setsnackmsg] = usestate("");

  const ontogglesnackbar = () => setvisible(!visible);
  const ondismisssnackbar = () => setvisible(false);
  . . .

  return (
    <view style={styles.container}>
    . . .
      <snackbar duration={2000} visible={visible} ondismiss={ondismisssnackbar}>
        {snackmsg}
      </snackbar>
    </view>
  );
}

由于 state 和 city 字段有父字段,因此必须验证它们。

        <Text>State</Text>
        <ZDropDown          
          onFocus={() => {
            focusField('state');
            if (!country.value) {
              setSnackMsg('Select country');
              onToggleSnackBar();
              focusField('country');
            }
          }}
          . . .
        />
        <Text>City</Text>
        <ZDropDown          
          onFocus={() => {
            focusField('city');
            if (!country.value) {
              setSnackMsg('Select country');
              onToggleSnackBar();
              focusField('country');
            } else if (!state.value) {
              setSnackMsg('Select state');
              onToggleSnackBar();
              focusField('state');
            }
          }}
          . . .
        />

是的,就是这样!我们完成了。谢谢。

完整代码参考这里

以上就是React Native 的基本级联形式的详细内容,更多请关注php中文网其它相关文章!