前言:
此刻我们对“前端自定义控件有哪些”大概比较关切,姐妹们都需要了解一些“前端自定义控件有哪些”的相关知识。那么小编同时在网上汇集了一些对于“前端自定义控件有哪些””的相关内容,希望姐妹们能喜欢,姐妹们一起来了解一下吧!组件效果图:
现有方案壁垒:
如果你做的是前端开发,你可能会经常遇到长度不够或高度不够时进行文本省略,这个也很简单,如下css代码就可以实现1行或n行的自动省略:
/*一行多余省略:*/.t-text-oneline { overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}/*n行多余省略:*/.t-text-nline { display: -webkit-box; word-break: break-all; text-overflow: ellipsis; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2; /*只需改变这里值为n即可*/}
上面针对多余文字通过省略隐藏达到样式不变的效果,但是用户无法看到内容的全部文字,或者说需要一些处理才可以让用户看到,例如点击跳转详情页展示或者tip提示组件等,总之用起来缺乏“美感”。
场景描述:
文本要能全部展示,而且通过用户主动触发展示与不展示。因为用户一般只会对自己感兴趣的文章才会看全文,这样就需要一个既能满足上面简单需求,又能满足全文查看,且方便用户操作的体验友好的组件,这也是本组件编写的目的。
兼容性:
需要全端兼容所以使用uniapp框架,满足easycom组件规范,用户导入hbuilder后直接通过标签引用使用,非常方便。
实现原理:
根据原view设置的默认显示行数、文字大小等信息,虚拟一个相同的view容器,该view中把文字全部展示出来,通过以上信息计算出每行大概有多少个字符(汉字算两个,其他算1个),根据字符数对全文内容进行截取,再通过原view高度和虚拟view高度比较如果相等则停止计算,得到最终需要显示的字符串进行渲染。
直接上正文,自定义组件全过程:
1.hbuilder新建一个项目,选择默认第一个hello uniapp模板即可;
2.项目根目录下新建components目录;
3.在components目录下新建组件目录,例如这里命名为kevy-ellipsis的组件目录;
4.在kevy-ellipsis目录下新建kevy-ellipsis.vue文件,其内容为组件代码
kevy-ellipsis.vue代码如下:
<template> <view class="t-wrap"> <!-- 虚拟view用于计算,计算完成则消失 --> <view class="t-txt-hide" :id="hid" v-if="!isCompute" :style="[computeStyle(0)]"> {{testContent?testContent:content}}{{showSymbol?'...':''}}<text v-if="expandText && collapseText" class="t-button"> {{expandText}} </text> </view> <!-- 真实显示的内容 --> <view class="t-ellipsis" :id="id" :style="[!isCompute?computeStyle(1):computeStyle(2)]" @click="contentClick"> {{(!isCompute || expand)?content:(actualContent+(showSymbol?'...':''))}}<text v-if="expandText && collapseText && showSymbol" class="t-button" @click.stop="changeCollapse" :style="{'color':actionFontColor,'float':'right'}">{{!expand?expandText:collapseText}}</text> </view> <!-- 这里加入了自定义的动态骨架屏友好反馈 --> <view v-if="!isCompute && rows>0" class="t-skeleton"> <view class="skeletons" v-for="(item,index) in rows"> <view class="empty"></view> </view> </view> </view></template><script> import { init, computeStyle, compute } from './kevy-ellipsis.min.js' export default { name: "kevy-ellipsis", props: { /** * 文本内容,默认'' */ content: { type: String, default: '' }, /** * 字体大小,单位rpx,默认28 */ fontSize: { type: Number, default: '28' }, /** * 字体颜色,默认#666666 */ fontColor: { color: String, default: '#666666' }, /** * 收起操作的文案,默认'' */ collapseText: { type: String, default: '' }, /** * 展开操作的文案,默认'' */ expandText: { type: String, default: '' }, /** * 收起、展开操作文字颜色,默认'#007aff' */ actionFontColor: { color: String, default: '#007aff' }, /** * 展示行数,默认1 */ rows: { type: Number, default: 1 }, }, data() { return { //是否展开 expand: false, //是否已计算 isCompute: false, //内容高度 h: undefined, //内容宽度 w: undefined, //实际显示内容 actualContent: '', //高度探测内容 testContent: undefined, //是否显示省略号 showSymbol: false, //hid和id,唯一标识符 hid: 'hid' + Math.random().toString(36).substr(2), id: 'id' + Math.random().toString(36).substr(2), }; }, created() { if (this.content?.length > 0) { // #ifdef H5 this.$nextTick(() => { init(this, () => { compute(this); }) }) // #endif // #ifdef MP-ALIPAY init(this, () => { compute(this, true); }, true) // #endif // #ifndef MP-ALIPAY || H5 init(this, () => { compute(this); }) // #endif } }, computed: { computeStyle }, methods: { //收起展开状态切换 changeCollapse() { this.expand = !this.expand; }, //文本点击事件 contentClick() { this.$emit('contentClick'); } } }</script><style lang="scss" scoped> .t-wrap { width: 100%; box-sizing: border-box; position: relative; } .t-txt-hide { word-break: break-word; position: absolute; top: 999999px; left: 999999px; z-index: -1000; top: 0rpx; width: 100%; margin: 0rpx; text-align: justify; } .t-ellipsis { text-align: justify; box-sizing: border-box; width: 100%; word-break: break-word; position: relative; left: 99999px; } .t-skeleton{ width: 100%; height: 100%; box-sizing: border-box; position: absolute; top: 0rpx; left: 0rpx; } .skeletons:first-child{ margin-top: 0rpx !important; } .skeletons { position: relative; display: block; overflow: hidden; width: 100%; height: 32rpx; margin-top: 12rpx; background-color: rgba(0, 0, 0, 0.06); box-sizing: border-box; } .skeletons .empty { display: block; position: absolute; width: 100%; height: 100%; -webkit-transform: translateX(-100%); transform: translateX(-100%); background: linear-gradient(90deg, transparent, rgba(216, 216, 216, 0.753), transparent); -webkit-animation: loading .8s infinite; animation: loading .8s infinite; } @keyframes loading { 100% { -webkit-transform: translateX(100%); transform: translateX(100%); } }</style>
5.在kevy-ellipsis同目录下新建kevy-ellipsis.min.js,即上面代码中引入的工具类,为了防止他人冒用这里进行了代码混淆(如需该工具类源码关注并评论回复留下邮箱),代码如下:
"use strict";function _typeof(e){return(_typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function ownKeys(t,e){var o,n=Object.keys(t);return Object.getOwnPropertySymbols&&(o=Object.getOwnPropertySymbols(t),e&&(o=o.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),n.push.apply(n,o)),n}function _objectSpread(t){for(var e=1;e<arguments.length;e++){var o=null!=arguments[e]?arguments[e]:{};e%2?ownKeys(Object(o),!0).forEach(function(e){_defineProperty(t,e,o[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(o)):ownKeys(Object(o)).forEach(function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(o,e))})}return t}function _defineProperty(e,t,o){return(t=_toPropertyKey(t))in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function _toPropertyKey(e){e=_toPrimitive(e,"string");return"symbol"===_typeof(e)?e:String(e)}function _toPrimitive(e,t){if("object"!==_typeof(e)||null===e)return e;var o=e[Symbol.toPrimitive];if(void 0===o)return("string"===t?String:Number)(e);o=o.call(e,t||"default");if("object"!==_typeof(o))return o;throw new TypeError("@@toPrimitive must return a primitive value.")}var init=function(t,o,e){(e?uni.createSelectorQuery().in().select("#"+t.id).boundingClientRect(function(e){t.h=Number(e.height.toFixed(1)),o&&o()}):uni.createSelectorQuery().in(t).select("#"+t.id).boundingClientRect(function(e){t.h=Number(e.height.toFixed(1)),o&&o()})).exec()},computeStyle=function(n){return function(e){var t=0<n.rows?n.rows:1,o={};return 1==e?o={"-webkit-line-clamp":t,display:"-webkit-box","text-overflow":"ellipsis",overflow:"hidden","-webkit-box-orient":"vertical"}:2==e&&(o=_objectSpread({position:"relative",left:"0rpx"},o)),_objectSpread({"font-size":n.fontSize+"rpx",color:n.fontColor},o)}},computeContent=function t(e,o,n,r){var i=e,c=i.h,u=i.testContent,l=i.content;l.length;i.testContent=u?n?l.substring(0,n):u:l,i.$nextTick(function(){getH(e,o,function(e){c<e?(i.showSymbol=!0,-1===r||void 0===r?t(i,o,Math.floor(i.testContent.length/2),-1):1===r&&(i.actualContent=l.substring(0,n-1),i.isCompute=!0)):i.showSymbol?-1!==r&&1!==r||t(i,o,n+1,1):(i.actualContent=l,i.isCompute=!0)})})},getH=function(e,t,o){(t?uni.createSelectorQuery().in().select("#"+e.hid).fields({size:!0},function(e){o(Number(e.height.toFixed(1)))}):uni.createSelectorQuery().in(e).select("#"+e.hid).fields({size:!0},function(e){o(Number(e.height.toFixed(1)))})).exec()};module.exports={init:init,computeStyle:computeStyle,computeContent:computeContent};
组件使用
<template> <view class="content"> <!-- 这里模拟通过请求js动态赋值 --> <kevy-ellipsis v-if="content && content.length>0" :content="content" font-color="#666666" :font-size="32" :rows="3" @contentClick="myclick" collapseText="收起" expandText="展开" actionFontColor="#007aff"></kevy-ellipsis> <view class="mg"></view> <!-- 这里模拟直接复制给组件(例如循环) --> <kevy-ellipsis content="这是一个uniapp通用的超长文本处理组件,简单的设置达到自动适配超长文本溢出兼容效果。这是一个uniapp通用的超长文本处理组件,简单的设置达到自动适配超长文本溢出兼容效果。这是一个uniapp通用的超长文本处理组件,简单的设置达到自动适配超长文本溢出兼容效果。这是一个uniapp通用的超长文本处理组件,简单的设置达到自动适配超长文本溢出兼容效果。这是一个uniapp通用的超长文本处理组件,简单的设置达到自动适配超长文本溢出兼容效果。这是一个uniapp通用的超长文本处理组件,简单的设置达到自动适配超长文本溢出兼容效果。" font-color="#666666" :font-size="32" :rows="3" @contentClick="myclick" collapseText="收起" expandText="展开" actionFontColor="#007aff"></kevy-ellipsis> </view></template><script> import kevyEllipsis from '@/components/kevy-ellipsis/kevy-ellipsis' export default { components: { kevyEllipsis }, data() { return { content:"" } }, onLoad() { //这里模拟请求到数据赋值给组件 this.content="这是一个uniapp通用的超长文本处理组件,简单的设置达到自动适配超长文本溢出兼容效果。这是一个uniapp通用的超长文本处理组件,简单的设置达到自动适配超长文本溢出兼容效果。这是一个uniapp通用的超长文本处理组件,简单的设置达到自动适配超长文本溢出兼容效果。这是一个uniapp通用的超长文本处理组件,简单的设置达到自动适配超长文本溢出兼容效果。这是一个uniapp通用的超长文本处理组件,简单的设置达到自动适配超长文本溢出兼容效果。这是一个uniapp通用的超长文本处理组件,简单的设置达到自动适配超长文本溢出兼容效果。"; }, methods: { //点击文本 myclick(){ console.log("哈哈,你点击文本了。。。"); } } }</script><style scoped> .content { box-sizing: border-box; width: 100%; padding: 24rpx; } .mg{ padding: 50rpx; }</style>方法和属性
名称
类型
描述
content
String
文本内容,默认’’
rows
Number
展示行数,默认1
fontSize
Number
文本字体大小,单位rpx,默认28
fontColor
String
文本字体颜色,默认#666666
collapseText
String
收起操作的文案,默认’’
expandText
String
展开操作的文案,默认’’
actionFontColor
String
收起、展开操作文字颜色,默认’#007aff’
contentClick
Func
文本点击事件函数
如果想用现成的,在插件详情页通过hbuilder直接导入即可,插件市场插件详情页地址为:
如果本文对您有帮助,还请帮忙点个赞或留下宝贵意见哦,总之谢谢您啦。
标签: #前端自定义控件有哪些