@gyenno/nutui-taro
Version:
京东风格的轻量级移动端 Vue2、Vue3 组件库(支持小程序开发)
285 lines (284 loc) • 10.2 kB
JavaScript
import { ref, reactive, computed, onMounted, unref, toRefs, openBlock, createElementBlock, createElementVNode, normalizeClass, toDisplayString, createCommentVNode, createTextVNode, withModifiers, normalizeStyle } from "vue";
import { c as createComponent } from "./component-25dcca32.js";
import { u as useTaroRect } from "./index-7fb26863.js";
import Taro from "@tarojs/taro";
import { _ as _export_sfc } from "./_plugin-vue_export-helper-cc2b3d55.js";
import "../locale/lang";
const { componentName, create } = createComponent("ellipsis");
const _sfc_main = create({
props: {
content: {
type: String,
default: ""
},
direction: {
type: String,
default: "start"
},
rows: {
type: [Number, String],
default: 1
},
expandText: {
type: String,
default: ""
},
collapseText: {
type: String,
default: ""
},
symbol: {
type: String,
default: "..."
},
lineHeight: {
type: [Number, String],
default: "20"
}
},
emits: ["click", "change"],
setup(props, { emit }) {
const root = ref(null);
const rootContain = ref(null);
const symbolContain = ref(null);
let contantCopy = ref(props.content);
let maxHeight = 0;
let lineHeight = 0;
let originHeight = 0;
const ellipsis = reactive({});
const refRandomId = Math.random().toString(36).slice(-8);
let widthRef = ref("auto");
const state = reactive({
exceeded: false,
//是否超出
expanded: false
//是否折叠
});
let widthBase = [14, 10, 7, 8.4, 10];
let symbolTextWidth = widthBase[0] * 0.7921;
const chineseReg = /^[\u4e00-\u9fa5]+$/;
const digitReg = /^[0-9]+$/;
const letterUpperReg = /^[A-Z]+$/;
const letterLowerReg = /^[a-z]+$/;
const classes = computed(() => {
const prefixCls = componentName;
return {
ell: true,
[prefixCls]: true
};
});
const symbolText = computed(() => {
if (props.direction == "end" || props.direction == "middle") {
return `${props.symbol}${props.expandText}`;
}
return `${props.symbol}${props.expandText}${props.symbol}`;
});
onMounted(() => {
setTimeout(() => {
getSymbolInfo();
getReference();
}, 100);
});
const getSymbolInfo = async () => {
const refe = await useTaroRect(symbolContain);
symbolTextWidth = refe.width ? Math.ceil(refe.width) : Math.ceil(widthBase[0] * 0.7921);
};
const getReference = async () => {
let element = unref(root);
const query = Taro.createSelectorQuery();
query.select(`#${element.id}`) && query.select(`#${element.id}`).fields(
{
computedStyle: ["width", "height", "lineHeight", "paddingTop", "paddingBottom", "fontSize"]
},
(res) => {
lineHeight = pxToNumber(res.lineHeight === "normal" ? props.lineHeight : res.lineHeight);
maxHeight = Math.floor(
lineHeight * (Number(props.rows) + 0.5) + pxToNumber(res.paddingTop) + pxToNumber(res.paddingBottom)
);
originHeight = pxToNumber(res.height);
widthRef.value = res.width;
const bsize = pxToNumber(res.fontSize);
widthBase = [bsize, bsize * 0.72, bsize * 0.53, bsize * 0.4, bsize * 0.75];
calcEllipse();
}
).exec();
};
const calcEllipse = async () => {
const refe = await useTaroRect(rootContain);
if (refe.height <= maxHeight) {
state.exceeded = false;
} else {
const rowNum = Math.floor(props.content.length / (originHeight / lineHeight - 1));
if (props.direction === "middle") {
const end = props.content.length;
ellipsis.leading = tailorContent(0, rowNum * (Number(props.rows) + 0.5), "end");
ellipsis.tailing = tailorContent(props.content.length - rowNum * (Number(props.rows) + 0.5), end, "start");
} else if (props.direction === "end") {
const end = rowNum * (Number(props.rows) + 0.5);
ellipsis.leading = tailorContent(0, end);
} else {
const start = props.content.length - rowNum * (Number(props.rows) + 0.5) - 5;
ellipsis.tailing = tailorContent(start, props.content.length);
}
assignContent();
setTimeout(() => {
verifyEllipsis();
}, 100);
}
};
const verifyEllipsis = async () => {
var _a, _b;
const refe = await useTaroRect(rootContain);
if (refe && refe.height && refe.height > maxHeight) {
if (props.direction == "end") {
ellipsis.leading = (_a = ellipsis.leading) == null ? void 0 : _a.slice(0, ellipsis.leading.length - 1);
} else {
ellipsis.tailing = (_b = ellipsis.tailing) == null ? void 0 : _b.slice(1, ellipsis.tailing.length);
}
assignContent();
setTimeout(() => {
verifyEllipsis();
}, 100);
}
};
const assignContent = () => {
contantCopy.value = `${ellipsis.leading || ""}${ellipsis.leading ? props.symbol : ""}${props.expandText || ""}${ellipsis.tailing ? props.symbol : ""}${ellipsis.tailing || ""}`;
};
const tailorContent = (left, right, type = "") => {
const threeDotWidth = symbolTextWidth;
const direc = props.direction === "middle" && type ? type : props.direction;
state.exceeded = true;
let widthPart = -1;
let start = left;
let end = right;
let cutoff = 0;
let marking = 0;
if (direc === "end") {
marking = start;
cutoff = end;
} else {
marking = end;
cutoff = start;
}
let contentWidth = pxToNumber(widthRef.value) * Number(props.rows) - threeDotWidth;
let contentPartWidth = props.direction === "middle" ? contentWidth / 2 : contentWidth;
while (widthPart < contentPartWidth) {
const zi = props.content[marking];
if (chineseReg.test(zi)) {
widthPart = Number(widthPart + widthBase[0]);
} else if (letterUpperReg.test(zi)) {
widthPart = Number(widthPart + widthBase[1]);
} else if (letterLowerReg.test(zi)) {
widthPart = Number(widthPart + widthBase[2]);
} else if (digitReg.test(zi)) {
widthPart = Number(widthPart + widthBase[3]);
} else {
widthPart = Number(widthPart + widthBase[4]);
}
cutoff = marking;
direc === "end" ? marking++ : marking--;
}
if (direc === "end") {
return props.content.slice(0, cutoff);
} else {
return props.content.slice(cutoff, end);
}
};
const pxToNumber = (value) => {
if (!value)
return 0;
const match = value.match(/^\d*(\.\d*)?/);
return match ? Number(match[0]) : 0;
};
const clickHandle = (type) => {
if (type == 1) {
state.expanded = true;
emit("change", "expand");
} else {
state.expanded = false;
emit("change", "collapse");
}
};
const handleClick = () => {
emit("click");
};
return {
...toRefs(state),
root,
rootContain,
symbolContain,
ellipsis,
classes,
contantCopy,
symbolText,
clickHandle,
handleClick,
refRandomId,
widthRef
};
}
});
const _hoisted_1 = ["id"];
const _hoisted_2 = {
key: 0,
class: "nut-ellipsis__wordbreak"
};
const _hoisted_3 = {
key: 1,
class: "nut-ellipsis__wordbreak"
};
const _hoisted_4 = { key: 2 };
const _hoisted_5 = ["id"];
const _hoisted_6 = ["id"];
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return openBlock(), createElementBlock("view", null, [
createElementVNode("view", {
class: normalizeClass(_ctx.classes),
onClick: _cache[2] || (_cache[2] = (...args) => _ctx.handleClick && _ctx.handleClick(...args)),
ref: "root",
id: "root" + _ctx.refRandomId
}, [
!_ctx.exceeded ? (openBlock(), createElementBlock("view", _hoisted_2, toDisplayString(_ctx.content), 1)) : createCommentVNode("", true),
createTextVNode(),
_ctx.exceeded && !_ctx.expanded ? (openBlock(), createElementBlock("view", _hoisted_3, [
createTextVNode(toDisplayString(_ctx.ellipsis.leading) + toDisplayString(_ctx.ellipsis.leading && _ctx.symbol), 1),
_ctx.expandText ? (openBlock(), createElementBlock("view", {
key: 0,
class: "nut-ellipsis__text",
onClick: _cache[0] || (_cache[0] = withModifiers(($event) => _ctx.clickHandle(1), ["stop"]))
}, toDisplayString(_ctx.expandText), 1)) : createCommentVNode("", true),
createTextVNode(toDisplayString(_ctx.ellipsis.tailing && _ctx.symbol) + toDisplayString(_ctx.ellipsis.tailing), 1)
])) : createCommentVNode("", true),
createTextVNode(),
_ctx.exceeded && _ctx.expanded ? (openBlock(), createElementBlock("view", _hoisted_4, [
createTextVNode(toDisplayString(_ctx.content) + " ", 1),
_ctx.expandText ? (openBlock(), createElementBlock("span", {
key: 0,
class: "nut-ellipsis__text",
onClick: _cache[1] || (_cache[1] = withModifiers(($event) => _ctx.clickHandle(2), ["stop"]))
}, toDisplayString(_ctx.collapseText), 1)) : createCommentVNode("", true)
])) : createCommentVNode("", true)
], 10, _hoisted_1),
createTextVNode(),
createElementVNode("view", {
class: "nut-ellipsis__copy",
ref: "rootContain",
id: "rootContain" + _ctx.refRandomId,
style: normalizeStyle({ width: _ctx.widthRef })
}, [
createElementVNode("view", null, toDisplayString(_ctx.contantCopy), 1)
], 12, _hoisted_5),
createTextVNode(),
createElementVNode("view", {
class: "nut-ellipsis__copy",
ref: "symbolContain",
id: "symbolContain" + _ctx.refRandomId,
style: { "display": "inline" }
}, toDisplayString(_ctx.symbolText), 9, _hoisted_6),
createTextVNode()
]);
}
const index_taro = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
export {
index_taro as default
};