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


相关文章
|
9月前
|
缓存 前端开发 JavaScript
React Hooks深度解析与最佳实践:提升函数组件能力的终极指南
🌟蒋星熠Jaxonic,前端探索者。专注React Hooks深度实践,从原理到实战,分享状态管理、性能优化与自定义Hook精髓。助力开发者掌握函数组件的无限可能,共赴技术星辰大海!
React Hooks深度解析与最佳实践:提升函数组件能力的终极指南
|
JavaScript 前端开发 API
对比Vue框架与React库的主要区别
在选择Vue还是React时,考虑项目的需求、团队的熟悉程度和个人偏好至关重要。如果项目需要快速原型开发和较小的学习曲线,Vue可能是更好的选择。相反,如果项目需要更大的灵活性,或者项目团队已经有React的经验,那么React可能是更合适的选择。
551 13
|
缓存 前端开发 数据安全/隐私保护
如何使用组合组件和高阶组件实现复杂的 React 应用程序?
如何使用组合组件和高阶组件实现复杂的 React 应用程序?
459 68
|
缓存 前端开发 Java
在 React 中,组合组件和高阶组件在性能方面有何区别?
在 React 中,组合组件和高阶组件在性能方面有何区别?
402 67
|
前端开发 JavaScript 安全
除了高阶组件和render props,还有哪些在 React 中实现代码复用的方法?
除了高阶组件和render props,还有哪些在 React 中实现代码复用的方法?
509 62
|
编解码 前端开发 开发者
React 图片组件样式自定义:常见问题与解决方案
在 React 开发中,图片组件的样式自定义常因细节问题导致布局错乱、性能损耗或交互异常。本文系统梳理常见问题及解决方案,涵盖基础样式应用、响应式设计、加载状态与性能优化等,结合代码案例帮助开发者高效实现图片组件的样式控制。重点解决图片尺寸不匹配、边框阴影不一致、移动端显示模糊、加载失败处理及懒加载等问题,并总结易错点和最佳实践,助力开发者提升开发效率和用户体验。
670 22
|
移动开发 前端开发 JavaScript
React音频播放列表组件:常见问题、易错点与解决方案
本文介绍了在React中实现音频播放列表时常见的挑战及解决方案。通过基础实现、常见问题分析和最佳实践,帮助开发者避免状态管理、生命周期控制和事件处理中的陷阱。关键点包括使用`useRef`操作音频元素、`useState`同步播放状态、全局状态管理防止多音频同时播放、以及通过`useEffect`清理资源。还提供了代码示例和跨浏览器兼容性处理方法,确保高效实现功能并减少调试时间。
480 30
|
移动开发 前端开发 UED
React 音频音量控制组件 Audio Volume Control
在现代Web应用中,音频播放功能不可或缺。React以其声明式编程和组件化开发模式,非常适合构建复杂的音频音量控制组件。本文介绍了如何使用HTML5 `&lt;audio&gt;`元素与React结合,实现直观的音量控制系统,并解决了常见问题如音量范围不合理、初始音量设置及性能优化等,帮助开发者打造优秀的音频播放器。
522 27
|
移动开发 前端开发 UED
React 音频进度条组件 Audio Progress Bar
在现代Web开发中,音频播放功能不可或缺。使用React构建音频进度条组件,不仅能实现播放控制和拖动跳转,还能确保代码的可维护性和复用性。本文介绍了如何利用HTML5 `&lt;audio&gt;`标签的基础功能、解决获取音频时长和当前时间的问题、动态更新进度条样式,并避免常见错误如忘记移除事件监听器和忽略跨浏览器兼容性。通过这些方法,开发者可以打造高质量的音频播放器,提升用户体验。
661 6
|
移动开发 前端开发 开发者
React 音频播放控制组件 Audio Controls
本文介绍了如何使用React构建音频播放控制组件,涵盖HTML5 `&lt;audio&gt;`标签和React组件化思想的基础知识。针对常见问题如播放状态管理、进度条更新不准确及跨浏览器兼容性,提供了详细的解决方案和代码示例。同时,还总结了易错点及避免方法,如确保音频加载完成再操作、处理音频错误等,帮助开发者实现稳定且功能强大的音频播放器。
557 11