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


相关文章
|
7天前
|
前端开发 JavaScript UED
React 图标库使用指南
本文详细介绍如何在 React 项目中使用 `react-icons` 等图标库,涵盖环境搭建、基础使用、常见问题与易错点、高级用法等内容,并通过代码案例进行说明。适合初学者和进阶开发者参考。
29 8
|
1月前
|
前端开发 JavaScript API
React开发需要了解的10个库
本文首发于微信公众号“前端徐徐”,介绍了React及其常用库。React是由Meta开发的JavaScript库,用于构建动态用户界面,广泛应用于Facebook、Instagram等知名网站。文章详细讲解了Axios、Formik、React Helmet、React-Redux、React Router DOM、Dotenv、ESLint、Storybook、Framer Motion和React Bootstrap等库的使用方法和应用场景,帮助开发者提升开发效率和代码质量。
119 4
React开发需要了解的10个库
|
12天前
|
前端开发 JavaScript 测试技术
React 分页组件 Pagination
本文介绍了如何在 React 中从零构建分页组件,涵盖基础概念、常见问题及解决方案。通过示例代码详细讲解了分页按钮的创建、分页按钮过多、初始加载慢、状态管理混乱等常见问题的解决方法,以及如何避免边界条件、性能优化和用户反馈等方面的易错点。旨在帮助开发者更好地理解和掌握 React 分页组件的开发技巧,提升应用的性能和用户体验。
42 0
|
1月前
|
前端开发 开发者
React 函数组件与类组件对比
【10月更文挑战第4天】本文详细比较了React中的函数组件与类组件。函数组件是一种简单的组件形式,以纯函数的形式返回JSX,易于理解与维护,适用于简单的UI逻辑。类组件则是基于ES6类实现的,需要重写`render`方法并能利用更多生命周期方法进行状态管理。文章通过示例代码展示了两者在状态管理与生命周期管理上的差异,并讨论了常见的问题如状态更新异步性与生命周期管理的复杂性,最后给出了相应的解决方法。通过学习,开发者可以根据具体需求选择合适的组件类型。
56 8
|
1月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
175 2
|
16天前
|
移动开发 前端开发 API
React 拖拽组件 Drag & Drop
本文介绍了在 React 中实现拖拽功能的方法,包括使用原生 HTML5 Drag and Drop API 和第三方库 `react-dnd`。通过代码示例详细讲解了基本的拖拽实现、常见问题及易错点,帮助开发者更好地理解和应用拖拽功能。
47 9
|
11天前
|
前端开发 UED 开发者
React 分页组件 Pagination
本文介绍了如何在 React 中实现分页组件,从基础概念到常见问题及解决方案。分页组件用于将大量数据分成多个页面,提升用户体验。文章详细讲解了分页组件的基本结构、快速入门步骤、以及如何处理页面跳转不平滑、页码过多导致布局混乱、边界条件处理和数据加载延迟等问题。通过本文,读者可以全面了解并掌握 React 分页组件的开发技巧。
17 2
|
15天前
|
设计模式 前端开发 编译器
与普通组件相比,React 泛型组件有哪些优势?
与普通组件相比,React 泛型组件有哪些优势?
31 6
|
23天前
|
前端开发 JavaScript 安全
学习如何为 React 组件编写测试:
学习如何为 React 组件编写测试:
36 2
|
30天前
|
前端开发 JavaScript 测试技术
React 高阶组件 (HOC) 应用
【10月更文挑战第16天】高阶组件(HOC)是 React 中一种复用组件逻辑的方式,通过接受一个组件并返回新组件来实现。本文介绍了 HOC 的基础概念、核心功能和常见问题,包括静态方法丢失、ref 丢失、多个 HOC 组合和 props 冲突的解决方案,并提供了具体的 React 代码示例。通过本文,读者可以更好地理解和应用 HOC,提高代码的复用性和可维护性。
59 8