Taro+react+TaroUi封装一个公司库的下拉组件

简介: Taro+react+TaroUi封装一个公司库的下拉组件

前言

歌谣 歌谣 如何封装一个公司库的一个组件


需求介绍

首先要实现的是


1第一步 需要在一个input框中输入字符 当字符发生变化的时候进行接口的调用


2超过两个字符开始渲染页面


3将页面的值返回出去


核心代码部分

``` import Taro, { Component } from "@tarojs/taro"; import { View, Text, Input, Form, ScrollView } from "@tarojs/components";


import { AtList, AtListItem, AtAccordion } from "taro-ui"; import { searchCompanyLibrary } from "@/services/user"; import "./index.scss"; /* * @param placeholder String 默认请输入 * @param title String 输入框名字【required】 * @param clear Boolean 是否显示清楚按钮 * @param searchCompanyLibrary Function 获取列表数据 [required] 接口请求 * @param searchCompanyLibraryList 回调传值 第一个参数为外层需要的文本值 第二个参数为控制外面元素是不是存在的值 * @param companyName 用于编辑回显使用 外层传入 * @param ScrollView 滚动取值 * ***** */ class FuzzyQuery extends Component { state = { applicantName: this.props.companyName || "", popLeft: 0, popWidth: 0, open: false, dataSource: [1, 2, 3], popTop: 0, selectItem: {}, isSelectCompany: false, pageIndex: 1, pageSize: 10 }; componentDidMount() { this.props.onRef && this.props.onRef(this); setTimeout(() => { this.handleGetDom(); }, 100); // this.handleGetDom(); } handleGetDom = () => { let _this = this; Taro.createSelectorQuery() .select(".fuzzy-query .weui-input") .boundingClientRect(function(rect) { // rect.id; // 节点的ID // rect.dataset; // 节点的dataset // rect.left; // 节点的左边界坐标 // rect.right; // 节点的右边界坐标 // rect.top; // 节点的上边界坐标 // rect.bottom; // 节点的下边界坐标 // rect.width; // 节点的宽度 // rect.height; // 节点的高度


_this.setState({
      popLeft: rect.left,
      popWidth: rect.width,
      popTop: rect.height
    });
  })
  .exec();
}; //选中某一项时触发 handleClick = (e, item) => { console.log(e, "e"); e.stopPropagation(); e.preventDefault();
this.setState(
  {
    open: false,
    applicantName: item.name,
    selectItem: item
  },
  () => {
    const { open } = this.state;
    this.props.searchCompanyLibraryList &&
      this.props.searchCompanyLibraryList(item.name, open);
  }
);
}; //当输入框发生变化时 handleChange = async keyWord => { var company = keyWord.detail.value; //先编码 var value = encodeURI(keyWord.detail.value); console.log(value, "value");


//如果少于2个字符,是不调用接口的,此时不显示公司公司列表弹窗,且将数据清空
if (company.length < 2) {
  this.setState(
    {
      applicantName: company,
      open: false,
      dataSource: [],
      pageIndex: 1
    },
    () => {
      const { open } = this.state;
      this.props.searchCompanyLibraryList &&
        this.props.searchCompanyLibraryList(company, open);
    }
  );
  Taro.showToast({
    title: "请输入不少于两个字符",
    icon: "none",
    mask: true
  });
} else {
  const { pageIndex, pageSize, dataSource, open } = this.state;
  let params = { keyWord: decodeURI(value), pageSize, pageIndex };
  const data = await searchCompanyLibrary(params);
  this.setState(
    {
      open: true,
      applicantName: company,
      dataSource: data.data.data,
      pageIndex: 1
    },
    () => {
      const { open } = this.state;
      this.props.searchCompanyLibraryList &&
        this.props.searchCompanyLibraryList(company, open);
    }
  );
}



};


//触底函数 onScrollToUpper = async () => { console.log("我在触底");
const { pageIndex, pageSize, dataSource, applicantName } = this.state;
let applicantNameList = encodeURI(applicantName);
let params = {
  keyWord: decodeURI(applicantNameList),
  pageSize,
  pageIndex: pageIndex + 1
};
const data = await searchCompanyLibrary(params);
console.log(dataSource, "dataSource");
console.log(data.data.data, "data");
this.setState({
  // open: true,
  // applicantName: applicantName,
  dataSource: [...dataSource, ...data.data.data],
  pageIndex: pageIndex + 1
});



}; render() { const { applicantName, popLeft, popWidth, open, popTop, dataSource } = this.state; console.log(dataSource, "dataSource"); const scrollStyle = { zIndex: 100, height: "250px" }; const { placeholder = "请输入", title = "", clear = false } = this.props; return ( {title}


{clear && applicantName && (




<span className="taro-text at-icon

1.

at-icon-close-circle at-input__icon-close">


)}




<View
      style={{ top: `${popTop * 2}px` }}
      className={
        open
          ? "show-fuzzy-pop position-absolute fuzzy-query-pop"
          : "position-absolute fuzzy-query-pop"
      }
    >
      <ScrollView
        scrollY
        style={scrollStyle}
        scrollWithAnimation
        onScrollToLower={this.onScrollToUpper}



// 使用箭头函数的时候 可以这样写 onScrollToUpper={this.onScrollToUpper} > ${popLeft - 12}px, width: ${popWidth}px }} > {dataSource.length > 0 && dataSource.map(item => { return ( ); })}


export default FuzzyQuery; ```




样式部分

``` .fuzzy-query{ .at-list::after{border-top:0;} .fuzzy-query-pop{ // border: 1px solid #e8e8e8; box-sizing: border-box; z-index:100; width: 100%; background: #fff; // opacity: 0; max-height:0; overflow: hidden; transition:max-height 0.5s ; .at-listitem{ padding:20px; font-size: 28px; } .at-listitem::after{left:0;} } .show-fuzzy-pop{ max-height:800px;


z-index: 100;

// overflow-y: scroll;

1.

2.

} .input-wrap{ margin-left: 32px;


color:#333; font-size: 28px; .input-item{ position: relative; padding:24px 0 ; &::after{ content: ''; position: absolute; -webkit-transform-origin: center; -ms-transform-origin: center; transform-origin: center; -webkit-box-sizing: border-box; box-sizing: border-box; pointer-events: none; top: -50%; left: -50%; right: -50%; bottom: -50%; border: 0 solid #d6e4ef; -webkit-transform: scale(0.5); -ms-transform: scale(0.5); transform: scale(0.5); border-bottom-width: 1PX; }} .input_title{ width:172px; margin-right: 16px; } .search-input-wrap{width:calc(100% - 172px);position: relative; .fuzzy-clear{position: absolute;right:0;width:32px;height:32px}} .search-input-show-clear{width:480.12px;position: relative; .fuzzy-clear{position: absolute;right:0;width:32px;height:32px}}


input::-webkit-input-placeholder { color: rgb(204,204,204); }


input::-moz-placeholder { /* Mozilla Firefox 19+ */ color: rgb(204,204,204); }


input:-moz-placeholder { /* Mozilla Firefox 4 to 18 */ color: rgb(204,204,204); }


input:-ms-input-placeholder { /* Internet Explorer 10-11 */ color: rgb(204,204,204); }


}


} ```




实现思路介绍(接口调用在子组件执行还是父组件)

const { pageIndex, pageSize, dataSource, open } = this.state; let params = { keyWord: decodeURI(value), pageSize, pageIndex }; const data = await searchCompanyLibrary(params);




总结1

子组件中进行接口的调用并进行页面的渲染


实现思路介绍(get请求传入中文页面获取不到参数)

let applicantNameList = encodeURI(applicantName); let params = { keyWord: decodeURI(applicantNameList), pageSize, pageIndex: pageIndex + 1 };




总结2

先用encodeURI编码再用decodeURI解码


实现思路介绍(如何改变下拉的分页)

``` //触底函数 onScrollToUpper = async () => { console.log("我在触底");


const { pageIndex, pageSize, dataSource, applicantName } = this.state;
let applicantNameList = encodeURI(applicantName);
let params = {
  keyWord: decodeURI(applicantNameList),
  pageSize,
  pageIndex: pageIndex + 1
};
const data = await searchCompanyLibrary(params);
console.log(dataSource, "dataSource");
console.log(data.data.data, "data");
this.setState({
  // open: true,
  // applicantName: applicantName,
  dataSource: [...dataSource, ...data.data.data],
  pageIndex: pageIndex + 1
});


}; ```




总结3

ScrollView包裹 设置出现滚动条的高度 触底执行 并对数据用扩展运算符拼接


实现思路介绍(如何控制下拉选择的值渲染到input上)

{dataSource.length > 0 && dataSource.map(item => { return ( <AtListItem title={item.name} onClick={e => this.handleClick(e, item, "selectItem")} /> ); })}




总结4

事件多绑定一个参数进行赋值 点击触发 完成赋值


实现思路介绍(如何把子组件获取的值给到父组件)

this.props.searchCompanyLibraryList && this.props.searchCompanyLibraryList(company, open);




总结5

简单的子组件向着父组件传值


实现思路介绍(如何控制事件的冒泡)  

this.props.searchCompanyLibraryList && this.props.searchCompanyLibraryList(company, open);




总结6

open去控制外层dom元素的显隐


实现效果

image.png


相关文章
|
18天前
|
前端开发 JavaScript 网络架构
react对antd中Select组件二次封装
本文介绍了如何在React中对Ant Design(antd)的Select组件进行二次封装,包括创建MSelect组件、定义默认属性、渲染Select组件,并展示了如何使用Less进行样式定义和如何在项目中使用封装后的Select组件。
39 2
react对antd中Select组件二次封装
|
18天前
|
前端开发
React给antd中TreeSelect组件左侧加自定义图标icon
本文介绍了如何在React中为Ant Design的TreeSelect组件的每个树节点添加自定义图标,并解决了因缺少key属性而导致的警告问题,展示了如何通过递归函数处理treeData数据并为每个节点添加图标。
26 2
React给antd中TreeSelect组件左侧加自定义图标icon
|
18天前
|
前端开发
React添加路径别名alias、接受props默认值、并二次封装antd中Modal组件与使用
本文介绍了在React项目中如何添加路径别名alias以简化模块引入路径,设置组件props的默认值,以及如何二次封装Ant Design的Modal组件。文章还提供了具体的代码示例,包括配置Webpack的alias、设置defaultProps以及封装Modal组件的步骤和方法。
35 1
React添加路径别名alias、接受props默认值、并二次封装antd中Modal组件与使用
|
2天前
|
前端开发
react 封装防抖
react 封装防抖
13 4
|
2天前
|
JavaScript 前端开发 安全
使用 TypeScript 加强 React 组件的类型安全
【10月更文挑战第1天】使用 TypeScript 加强 React 组件的类型安全
10 3
|
1月前
|
消息中间件 前端开发
React技术栈-组件间通信的2种方式
本文介绍了React技术栈中组件间通信的两种方式:通过props传递数据和使用消息发布(publish)-订阅(subscribe)机制,并通过实例代码展示了如何使用PubSubJS库实现跨组件通信。
49 11
React技术栈-组件间通信的2种方式
|
1月前
|
前端开发
React技术栈-react使用的Ajax请求库实战案例
这篇文章介绍了在React应用中使用Axios和Fetch库进行Ajax请求的实战案例,展示了如何通过这些库发送GET和POST请求,并处理响应和错误。
36 10
React技术栈-react使用的Ajax请求库实战案例
|
14天前
|
前端开发 JavaScript 区块链
react18函数组件+antd使用指南-使用代码集合以及报错记录汇总
本文介绍了多个React开发中常见的问题及其解决方案,包括但不限于:1)`useForm`实例未连接到任何`Form`元素的警告及解决方法;2)监听页面滚动事件的实现方式;3)React 18与antd 5.8.6中定制主题的方法;4)React结合antd 4.x版本自定义主题色的步骤;5)解决`ResizeObserver loop`相关报错的技巧;6)处理React设计表单时遇到的CDN资源加载失败问题;7)解决onClick事件传参问题;8)修复类型错误等。每部分均提供详细分析与实用代码示例,帮助开发者快速定位并解决问题。
16 2
|
1月前
|
前端开发
React技术栈-react使用的Ajax请求库用户搜索案例
这篇文章展示了一个React技术栈中使用Ajax请求库(如axios)进行用户搜索的实战案例,包括React组件的结构、状态管理以及如何通过Ajax请求获取并展示GitHub用户数据。
27 7
React技术栈-react使用的Ajax请求库用户搜索案例
|
1月前
|
前端开发 Python
React技术栈-React路由插件之自定义组件标签
关于React技术栈中React路由插件自定义组件标签的教程。
46 4
React技术栈-React路由插件之自定义组件标签