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


相关文章
|
6天前
|
前端开发 UED 开发者
React 悬浮按钮组件 FloatingActionButton
悬浮按钮(FAB)是常见的UI元素,用于提供突出的操作。本文介绍如何在React中使用Material-UI创建美观的FAB组件,涵盖基本概念、实现方法及常见问题解决。通过代码示例和优化技巧,帮助开发者提升用户体验,确保按钮位置、颜色、交互反馈等方面的表现,同时避免无障碍性和性能问题。
107 80
|
14天前
|
前端开发 JavaScript 开发者
React 按钮组件 Button
本文介绍了 React 中按钮组件的基础概念,包括基本的 `&lt;button&gt;` 元素和自定义组件。详细探讨了事件处理、参数传递、状态管理、样式设置和可访问性优化等常见问题及其解决方案,并提供了代码示例。帮助开发者避免易错点,提升按钮组件的使用体验。
142 77
|
12天前
|
存储 前端开发 UED
React 面包屑组件 Breadcrumb 详解
面包屑导航是现代Web应用中常见的UI元素,帮助用户了解当前位置并快速返回上级页面。本文介绍如何使用React构建面包屑组件,涵盖基本概念、实现方法及常见问题。通过函数式组件和钩子,结合React Router动态生成路径,处理嵌套路由,并确保可访问性。示例代码展示了静态和动态面包屑的实现,帮助开发者提升用户体验。
120 73
|
15天前
|
前端开发 UED 开发者
React 对话框组件 Dialog
本文详细介绍了如何在 React 中实现一个功能完备的对话框组件(Dialog),包括基本用法、常见问题及其解决方案,并通过代码案例进行说明。从安装依赖到创建组件、添加样式,再到解决关闭按钮失效、背景点击无效、键盘导航等问题,最后还介绍了如何添加动画效果和处理异步关闭操作。希望本文能帮助你在实际开发中更高效地使用 React 对话框组件。
125 75
|
2月前
|
前端开发 JavaScript 测试技术
React 分页组件 Pagination
本文介绍了如何在 React 中从零构建分页组件,涵盖基础概念、常见问题及解决方案。通过示例代码详细讲解了分页按钮的创建、分页按钮过多、初始加载慢、状态管理混乱等常见问题的解决方法,以及如何避免边界条件、性能优化和用户反馈等方面的易错点。旨在帮助开发者更好地理解和掌握 React 分页组件的开发技巧,提升应用的性能和用户体验。
81 0
|
2月前
|
设计模式 前端开发 编译器
与普通组件相比,React 泛型组件有哪些优势?
与普通组件相比,React 泛型组件有哪些优势?
104 63
|
20天前
|
前端开发 Java API
React 进度条组件 ProgressBar 详解
本文介绍了如何在 React 中创建进度条组件,从基础实现到常见问题及解决方案,包括动态更新、状态管理、性能优化、高级动画效果和响应式设计等方面,帮助开发者构建高效且用户体验良好的进度条。
45 18
|
2月前
|
存储 前端开发 测试技术
React组件的最佳实践
React组件的最佳实践
|
2月前
|
前端开发 API 开发者
React 文件上传组件 File Upload
本文详细介绍了如何在 React 中实现文件上传组件,从基础的文件选择和上传到服务器,再到解决文件大小、类型限制、并发上传等问题,以及实现多文件上传、断点续传和文件预览等高级功能,帮助开发者高效构建可靠的应用。
60 12
|
28天前
|
存储 前端开发 JavaScript
React 表单输入组件 Input:常见问题、易错点及解决方案
本文介绍了在 React 中使用表单输入组件 `Input` 的基础概念,包括受控组件与非受控组件的区别及其优势。通过具体代码案例,详细探讨了创建受控组件、处理多个输入字段、输入验证和格式化的方法,并指出了常见易错点及避免方法,旨在提升表单的健壮性和用户体验。
37 4