uni-app 富文本组件editor无法正常使用

uni-app 富文本组件editor无法正常使用

项目信息 详细信息
产品分类 uniapp/H5
PC开发环境操作系统 Windows
PC开发环境操作系统版本号 10
HBuilderX类型 正式
HBuilderX版本号 3.99
浏览器平台 Chrome
浏览器版本 120.0.6099.217
项目创建方式 HBuilderX

示例代码:

<template>
<view class="jnpf-editor">
<template v-if="!detailed">
<view class='toolbar'>
<view :class="{'ql-active':formats.bold}" class="iconfont icon-zitijiacu" data-name="bold"
@tap="format"></view>
<view :class="{'ql-active':formats.italic}" class="iconfont icon-zitixieti" data-name="italic"
@tap="format"></view>
<view :class="{'ql-active':formats.underline}" class="iconfont icon-zitixiahuaxian"
data-name="underline" @tap="format"></view>
<view :class="{'ql-active':formats.strike}" class="iconfont icon-zitishanchuxian" data-name="strike"
@tap="format"></view>
<view :class="{'ql-active':formats.align==='left'}" class="iconfont icon-zuoduiqi" data-name="align"
data-value="left" @tap="format"></view>
<view :class="{'ql-active':formats.align==='center'}" class="iconfont icon-juzhongduiqi"
data-name="align" data-value="center" @tap="format"></view>
<view :class="{'ql-active':formats.align==='right'}" class="iconfont icon-youduiqi" data-name="align"
data-value="right" @tap="format"></view>
<view :class="{'ql-active':formats.align==='justify'}" class="iconfont icon-zuoyouduiqi"
data-name="align" data-value="justify" @tap="format"></view>
<view :class="{'ql-active':formats.lineHeight}" class="iconfont icon-line-height" data-name="lineHeight"
data-value="2" @tap="format"></view>
<view :class="{'ql-active':formats.letterSpacing}" class="iconfont icon-Character-Spacing"
data-name="letterSpacing" data-value="2em" @tap="format"></view>
<view :class="{'ql-active':formats.marginTop}" class="iconfont icon-722bianjiqi_duanqianju"
data-name="marginTop" data-value="20px" @tap="format"></view>
<view :class="{'ql-active':formats.marginBottom}" class="iconfont icon-723bianjiqi_duanhouju"
data-name="marginBottom" data-value="20px" @tap="format"></view>
<view class="iconfont icon-clearedformat" @tap="removeFormat"></view>
<view :class="{'ql-active':formats.fontFamily}" class="iconfont icon-font" data-name="fontFamily"
data-value="Pacifico" @tap="format"></view>
<view :class="{'ql-active':formats.fontSize === '24px'}" class="iconfont icon-fontsize"
data-name="fontSize" data-value="24px" @tap="format"></view>
<view :class="{'ql-active':formats.color === '#0000ff'}" class="iconfont icon-text_color"
data-name="color" data-value="#0000ff" @tap="format"></view>
<view :class="{'ql-active':formats.backgroundColor === '#00ff00'}" class="iconfont icon-fontbgcolor"
data-name="backgroundColor" data-value="#00ff00" @tap="format"></view>
<view class="iconfont icon-date" @tap="insertDate"></view>
<view class="iconfont icon--checklist" data-name="list" data-value="check" @tap="format"></view>
<view :class="{'ql-active':formats.list === 'ordered'}" class="iconfont icon-youxupailie"
data-name="list" data-value="ordered" @tap="format"></view>
<view :class="{'ql-active':formats.list === 'bullet'}" class="iconfont icon-wuxupailie" data-name="list"
data-value="bullet" @tap="format"></view>
<view class="iconfont icon-undo" @tap="undo"></view>
<view class="iconfont icon-redo" @tap="redo"></view>
<view class="iconfont icon-outdent" data-name="indent" data-value="-1" @tap="format"></view>
<view class="iconfont icon-indent" data-name="indent" data-value="+1" @tap="format"></view>
<view class="iconfont icon-fengexian" @tap="insertDivider"></view>
<view class="iconfont icon-charutupian" @tap="insertImage"></view>
<view :class="{'ql-active':formats.header === 1}" class="iconfont icon-format-header-1"
data-name="header" :data-value="1" @tap="format"></view>
<view :class="{'ql-active':formats.script === 'sub'}" class="iconfont icon-zitixiabiao"
data-name="script" data-value="sub" @tap="format"></view>
<view :class="{'ql-active':formats.script === 'super'}" class="iconfont icon-zitishangbiao"
data-name="script" data-value="super" @tap="format"></view>
<view class="iconfont icon-shanchu" @tap="clear"></view>
<view :class="{'ql-active':formats.direction === 'rtl'}" class="iconfont icon-direction-rtl"
data-name="direction" data-value="rtl" @tap="format"></view>
</view>
<view class="editor-wrapper">
<editor :id="id" class="ql-container" :placeholder="placeholder" showImgSize showImgToolbar
showImgResize @statuschange="onStatusChange" :read-only="disabled" [@ready](/user/ready)="onEditorReady"
@input="getValue"></editor>
</view>
</view>
<view v-else>
<mp-html class="editor-box" :content="modelValue" />
</view>
</template>
</view>
<script>
export default {
name: 'jnpf-editor',
props: {
modelValue: {
type: String,
default: ''
},
placeholder: {
type: String,
default: '请输入'
},
disabled: {
type: Boolean,
default: false
},
detailed: {
type: Boolean,
default: false
},
},
data() {
return {
innerValue: '',
readOnly: false,
formats: {},
editorChange: false,
id: 'jnpf-' + this.jnpf.idGenerator(),
}
},
watch: {
modelValue(val) {
if (this.editorChange && val) return
this.editorChange = false
this.editorCtx && this.editorCtx.setContents({
html: val
})
}
},
onLoad() {
uni.loadFontFace({
family: 'Pacifico',
source: 'url("https://sungd.github.io/Pacifico.ttf")'
})
},
methods: {
readOnlyChange() {
this.readOnly = !this.readOnly
},
onEditorReady() {
// #ifdef APP-PLUS || H5 ||MP-WEIXIN
uni.createSelectorQuery().in(this).select('#' + this.id).context((res) => {
this.editorCtx = res.context
this.editorCtx.setContents({
html: this.modelValue
})
}).exec()
// #endif
},
undo() {
this.editorCtx.undo()
},
redo() {
this.editorCtx.redo()
},
format(e) {
let {
name,
value
} = e.target.dataset
if (!name) return
this.editorCtx.format(name, value)
},
onStatusChange(e) {
const formats = e.detail
this.formats = formats
},
insertDivider() {
this.editorCtx.insertDivider()
},
clear() {
this.editorCtx.clear()
},
removeFormat() {
this.editorCtx.removeFormat()
},
insertDate() {
const date = new Date()
const formatDate = ${date.getFullYear()}/${date.getMonth() + 1}/${date.getDate()}
this.editorCtx.insertText({
text: formatDate
})
},
insertImage() {
uni.chooseImage({
count: 1,
success: (res) => {
this.getImageBase64(res)
}
})
},
getImageBase64(res) {
const image = res.tempFilePaths[0]
// #ifdef MP-WEIXIN
uni.getFileSystemManager().readFile({
filePath: image,
encoding: "base64",
success: (e) => {
this.insertImageVal('data:image/jpeg;base64,' + e.data)
},
});
// #endif
// #ifdef APP-PLUS
let path = plus.io.convertLocalFileSystemURL(image);
let fileReader = new plus.io.FileReader();
fileReader.readAsDataURL(path);
fileReader.onloadend = (e) => {
this.insertImageVal(e.target.result);
}
// #endif
// #ifdef H5
uni.request({
url: image, //临时路径
responseType: 'arraybuffer', //设置返回的数据格式为arraybuffer
success: res => {
const base64 = wx.arrayBufferToBase64(res.data)
this.insertImageVal('data:image/jpeg;base64,' + base64);
},
})
// #endif
},
insertImageVal(image) {
this.editorCtx.insertImage({
src: image,
alt: '图像',
success: function() {}
})
},
getValue(e) {
this.editorChange = true
let val = e.detail.text === '\n' ? '' : e.detail.html
this.$emit('update:modelValue', val)
}
}
}
</script>
<style lang="scss" scoped>
@import "./editor-icon.css";

:deep(.ql-editor) {  
word-break: break-all;  
}

.jnpf-editor {  
background-color: #fff;  

.iconfont {  
display: inline-block;  
width: 80rpx;  
height: 80rpx;  
cursor: pointer;  
font-size: 20px;  
line-height: 80rpx;  
text-align: center;  
}  

.toolbar {  
height: 240rpx;  
background: #f5f5f5;  
overflow-y: auto;  
box-sizing: border-box;  
border-bottom: 0;  
font-family: 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;  
}  

.ql-container {  
box-sizing: border-box;  
padding: 20rpx;  
width: 100%;  
height: 400rpx;  
margin-top: 20rpx;  
font-size: 30rpx;  
line-height: 1.5;  
}  

.ql-active {  
color: #06c;  
}  
}
</style>

操作步骤:

无法复现

预期结果:

正常使用就行

实际结果:

@ready 初始化方法都没有进入无法使用

bug描述:

editor组件无法使用


更多关于uni-app 富文本组件editor无法正常使用的实战教程也可以访问 https://www.itying.com/category-93-b0.html

35 回复

看到你在添加不同的 icon 实现功能,可以按照 hello uniapp 的 demo 进行修改,https://github.com/dcloudio/hello-uniapp/blob/a5f67bc39e42c665efb8bdba5b980a801273dfb8/pages/component/editor/editor.vue#L4

更多关于uni-app 富文本组件editor无法正常使用的实战教程也可以访问 https://www.itying.com/category-93-b0.html


你好!我发现在Microsoft Edge浏览器上也不行 版本 120.0.2210.133 (正式版本) (64 位)

回复 DCloud_UNI_OttoJi: 谷歌浏览器可以了

这段示例代码不方便我们定位你的问题,请提供一个简单复现的demo(zip压缩包附件上传

官网预览都不行https://hellouniapp.dcloud.net.cn/pages/component/editor/editor

之前我 vue2 搞定了,不知道怎么又回去了,而且左上角跳转 vue3 的内容也不见了,你瞧瞧

回复 DCloud_UNI_OttoJi: 我在一月十号的时候上传了一版,我下午核对一下版本差异

现在可以了谢谢

是按照文档和 hello uniapp 修改的吗,欢迎反馈

你好!我发现在Microsoft Edge浏览器上不行 版本 120.0.2210.133 (正式版本) (64 位)

用不了,看下是因为报错的原因,还是因为 network 访问了 unpkg 的原因?如果是后者可以参考 https://ask.dcloud.net.cn/article/40900 解决

你在之前显示正常后,你是做了什么修改才导致这个问题复现,方便贴一下代码吗

回复 HRK_01: 我都没有做如何修改

回复 s***@yinmaisoft.com: 目前新版本已发布到github,通过github克隆hello-uniapp项目并运行即可解决该问题,稍后会将最新版本同步到HBX新建的hello示例工程。

回复 HRK_01: 现在可以使用了,那请问这个富文本如何添加表格

回复 s***@yinmaisoft.com: 目前官方自带的富文本暂不支持添加表格,如果有需求,可到插件市场下载相关富文本插件使用 https://ext.dcloud.net.cn/search?q=富文本&cat1=3

我发现在vue3的时候 picker-view 这个控件的value传不进去 :value=“valueArr” 导致时间没办法定位到当前年月日 定位到了起始时间 就算这样写死也不生效 :value="[2,3,6]" 同样的数据vue2就可以

感谢反馈,我将尝试验证并在此更新进度

已复现该问题,感谢你的反馈,后续尝试修复,并在此贴更新

回复 HRK_01: 你好这个picker-view修复好了吗?

回复 s***@yinmaisoft.com: 你好,十分抱歉,之前的排查方式有误,现重新排查了一下,底层逻辑并无问题,发现并不是value不生效,而是传值的时候应该传数组的下标,而不是值。如果你传入下标还是不生效的话,能否提供一个简单的demo(zip压缩包)

回复 HRK_01: 我截图时传的就是数组下标,相同控件,相同数据,相同写法,在vue3就传不过去

回复 s***@yinmaisoft.com: 是app端,H5可以

还有两个页面反复打开来回切换会导致页面卡死,直到浏览器崩溃,app也是相同问题

回复 s***@yinmaisoft.com: 能否提供一下问题工程

回复 HRK_01: picker-view这个控件在vue3 app端 :value 值传不进去 写死数组下标也不行

回复 s***@yinmaisoft.com: 我在vue3中并未复现该问题哦,编译到IOS与安卓都能正常使用,能贴一下代码吗

<view class="u-picker-body"> <picker-view :value="valueArr" [@change](/user/change)="change" class="u-picker-view" [@pickstart](/user/pickstart)="pickstart" [@pickend](/user/pickend)="pickend"> <picker-view-column v-if="!reset && params.year"> <view class="u-column-item" v-for="(item, index) in years" :key="index"> {{ item }} <text class="u-text" v-if="showTimeTag">年</text> </view> </picker-view-column> <picker-view-column v-if="!reset && params.month"> <view class="u-column-item" v-for="(item, index) in months" :key="index"> {{ formatNumber(item) }} <text class="u-text" v-if="showTimeTag">月</text> </view> </picker-view-column> <picker-view-column v-if="!reset && params.day"> <view class="u-column-item" v-for="(item, index) in days" :key="index"> {{ formatNumber(item) }} <text class="u-text" v-if="showTimeTag">日</text> </view> </picker-view-column> <picker-view-column v-if="!reset && params.hour"> <view class="u-column-item" v-for="(item, index) in hours" :key="index"> {{ formatNumber(item) }} <text class="u-text" v-if="showTimeTag">时</text> </view> </picker-view-column> <picker-view-column v-if="!reset && params.minute"> <view class="u-column-item" v-for="(item, index) in minutes" :key="index"> {{ formatNumber(item) }} <text class="u-text" v-if="showTimeTag">分</text> </view> </picker-view-column> <picker-view-column v-if="!reset && params.second"> <view class="u-column-item" v-for="(item, index) in seconds" :key="index"> {{ formatNumber(item) }} <text class="u-text" v-if="showTimeTag">秒</text> </view> </picker-view-column> </picker-view> </view>回复 DCloud_UNI_HRK:
<script> export default { name: 'u-picker', props: { params: { type: Object, default () { return { year: true, month: true, day: true, hour: false, minute: false, second: false, timestamp: true, }; } }, // 当mode=selector或者mode=multiSelector时,提供的数组 range: { type: Array, default () { return []; } }, // 当mode=selector或者mode=multiSelector时,提供的默认选中的下标 defaultSelector: { type: Array, default () { return [0]; } }, // 当 range 是一个 Array<Object> 时,通过 range-key 来指定 Object 中 key 的值作为选择器显示内容 rangeKey: { type: String, default: '' }, // 模式选择,region-地区类型,time-时间类型,selector-单列模式,multiSelector-多列模式 mode: { type: String, default: 'time' }, // 年份开始时间 startDate: { type: String, default: '1899-01-01 00:00:00' }, // 年份结束时间 endDate: { type: String, default: '2250-12-31 23:59:59' }, // "取消"按钮的颜色 cancelColor: { type: String, default: '#606266' }, // "确定"按钮的颜色 confirmColor: { type: String, default: '#2979ff' }, // 默认显示的时间 defaultTime: { type: String, default: '' }, // 时间模式时,是否显示后面的年月日中文提示 showTimeTag: { type: Boolean, default: true }, safeAreaInsetBottom: { type: Boolean, default: false }, // 是否允许通过点击遮罩关闭Picker maskCloseAble: { type: Boolean, default: false }, // 通过双向绑定控制组件的弹出与收起 modelValue: { type: Boolean, default: false }, // 弹出的z-index值 zIndex: { type: [String, Number], default: 0 }, // 顶部标题 title: { type: String, default: '' }, // 取消按钮的文字 cancelText: { type: String, default: '取消' }, // 确认按钮的文字 confirmText: { type: String, default: '确认' }, format: { type: String, default: 'yyyy-MM-dd HH:mm:ss' } }, data() { return { years: [], months: [], days: [], hours: [], minutes: [], seconds: [], year: 0, month: 0, day: 0, hour: 0, minute: 0, second: 0, reset: false, valueArr: [], moving: false, // 列是否还在滑动中,微信小程序如果在滑动中就点确定,结果可能不准确 showPopup: false }; }, mounted() { this.init(); }, computed: { propsChange() { // 引用这几个变量,是为了监听其变化 return ${this.mode}-${this.defaultTime}-${this.startYear}-${this.endYear}-${this.defaultRegion}-${this.areaCode}; }, yearAndMonth() { return ${this.year}-${this.month}; }, uZIndex() { // 如果用户有传递z-index值,优先使用 return this.zIndex ? this.zIndex : this.$u.zIndex.popup; } }, watch: { propsChange() { this.reset = true; setTimeout(() => this.init(), 10); }, // watch监听月份的变化,实时变更日的天数,因为不同月份,天数不一样 // 一个月可能有30,31天,甚至闰年2月的29天,平年2月28天 yearAndMonth(val) { if (this.params.year) this.setDays(); }, // 微信和QQ小程序由于一些奇怪的原因(故同时对所有平台均初始化一遍),需要重新初始化才能显示正确的值 modelValue: { handler(val) { if (val) { this.showPopup = val this.reset = true; setTimeout(() => this.init(), 10); } }, immediate: true } }, methods: { // 标识滑动开始,只有微信小程序才有这样的事件 pickstart() { // #ifdef MP-WEIXIN this.moving = true; // #endif }, // 标识滑动结束 pickend() { // #ifdef MP-WEIXIN this.moving = false; // #endif }, getIndex: function(arr, val) { let index = arr.indexOf(val); // 如果index为-1(即找不到index值),~(-1)=-(-1)-1=0,导致条件不成立 return ~index ? index : 0; }, //日期时间处理 initTimeValue() { // 格式化时间,在IE浏览器(uni不存在此情况),无法识别日期间的"-"间隔符号 let fdate = this.defaultTime.replace(/-/g, '/'); fdate = fdate && fdate.indexOf('/') == -1 ? 1899/01/01 ${fdate} : fdate; let time = null; if (fdate) time = new Date(fdate); else time = new Date(); // 获取年日月时分秒 this.year = time.getFullYear(); this.month = Number(time.getMonth()) + 1; this.day = time.getDate(); this.hour = time.getHours(); this.minute = time.getMinutes(); this.second = time.getSeconds(); }, init() { this.valueArr = []; this.reset = false; this.initTimeValue(); if (this.params.year) { this.valueArr.push(0); this.setYears(); } if (this.params.month) { this.valueArr.push(0); this.setMonths(); } if (this.params.day) { this.valueArr.push(0); this.setDays(); } if (this.params.hour) { this.valueArr.push(0); this.setHours(); } if (this.params.minute) { this.valueArr.push(0); this.setMinutes(); } if (this.params.second) { this.valueArr.push(0); this.setSeconds(); } }, // 设置picker的某一列值 setYears() { // 获取年份集合 this.generateArray('year'); if (this.years[0] > this.year) this.year = this.years[0] if (this.years[this.years.length - 1] < this.year) this.year = this.years[this.years.length - 1] // 设置this.valueArr某一项的值,是为了让picker预选中某一个值 this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.years, this.year)); }, setMonths() { this.generateArray('month'); if (this.months[0] > this.month) this.month = this.months[0] if (this.months[this.months.length - 1] < this.month) this.month = this.months[this.months.length - 1] this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.months, this.month)); }, setDays() { let totalDays = new Date(this.year, this.month, 0).getDate(); this.generateArray('day'); let index = 0; // 这里不能使用类似setMonths()中的this.valueArr.splice(this.valueArr.length - 1, xxx)做法 // 因为this.month和this.year变化时,会触发watch中的this.setDays(),导致this.valueArr.length计算有误 if (this.params.year && this.params.month) index = 2; else if (this.params.month) index = 1; else if (this.params.year) index = 1; else index = 0; // 当月份变化时,会导致日期的天数也会变化,如果原来选的天数大于变化后的天数,则重置为变化后的最大值 // 比如原来选中3月31日,调整为2月后,日期变为最大29,这时如果day值继续为31显然不合理,于是将其置为29(picker-column从1开始) // if (this.day > this.days.length) this.day = this.days.length; if (this.days[0] > this.day) this.day = this.days[0] if (this.days[this.days.length - 1] < this.day) this.day = this.days[this.days.length - 1] this.valueArr.splice(index, 1, this.getIndex(this.days, this.day)); }, setHours() { this.generateArray('hour'); if (this.hours[0] > this.hour) this.hour = this.hours[0] if (this.hours[this.hours.length - 1] < this.hour) this.hour = this.hours[this.hours.length - 1] this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.hours, this.hour)); }, setMinutes() { this.generateArray('minute'); if (this.minutes[0] > this.minute) this.minute = this.minutes[0] if (this.minutes[this.minutes.length - 1] < this.minute) this.minute = this.minutes[this.minutes.length - 1] this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.minutes, this.minute)); }, setSeconds() { this.generateArray('second'); if (this.seconds[0] > this.second) this.second = this.seconds[0] if (this.seconds[this.seconds.length - 1] < this.second) this.second = this.seconds[this.seconds.length - 1] this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.seconds, this.second)); }, generateArray(type) { let startArr = this.startDate.split(" "); //开始日期时间 let endArr = this.endDate.split(" "); //结束日期时间 if (!this.month) this.month = this.months[this.months.length - 1] let totalDays = new Date(this.year, this.month, 0).getDate(); //当月天数 //开始年月日时分秒 let startDateArr = startArr[0] ? startArr[0].split("-") : []; //开始日期 let startTimeArr = startArr[1] ? startArr[1].split(":") : []; //开始时间 let startYear = Number(startDateArr[0]) || 1; //开始年 let startMonth = Number(startDateArr[1]) || 1; //开始月 let startDay = Number(startDateArr[2]) || 1; //开始天数 let startHour = Number(startTimeArr[0]) || 0 //开始小时 let startMinute = Number(startTimeArr[1]) || 0 //开始分钟 let startSecond = Number(startTimeArr[2]) || 0 //开始秒 //结束年月日时分秒 let endDateArr = endArr[0] ? endArr[0].split("-") : [] //结束日期 let endTimeArr = endArr[1] ? endArr[1].split(":") : []; //结束时间 let endYear = Number(endDateArr[0]) || 12; //结束年 let endMonth = Number(endDateArr[1]) || 12; //结束月 let endDay = Number(endDateArr[2]) || totalDays; //结束天数 let endHour = Number(endTimeArr[0]) || 0 //结束小时 let endMinute = Number(endTimeArr[1]) || 0 //结束分钟 let endSecond = Number(endTimeArr[2]) || 0 //结束秒 // 转为数值格式,否则用户给end-year等传递字符串值时,下面的end+1会导致字符串拼接,而不是相加 if (type == 'year') { startYear = Number(startYear); endYear = Number(endYear); endYear = endYear > startYear ? endYear : startYear; // 生成数组,获取其中的索引,并剪出来 this.years = [...Array(endYear + 1).keys()].slice(startYear); this.generateArray('month') } else if (type == 'month') { let months = [] if (startYear == Number(this.year)) { if (endYear == Number(this.year)) { // 起始年份,末尾年份一样时 months = [...Array(endMonth + 1).keys()].slice(startMonth); } else { months = [...Array(12 + 1).keys()].slice(startMonth); } } else if (endYear == Number(this.year)) { months = [...Array(endMonth + 1).keys()].slice(1); } else { months = [...Array(12 + 1).keys()].slice(1); } this.months = months this.generateArray('day') } else if (type === 'day') { let days = [] if (startYear == Number(this.year) && startMonth == Number(this.month)) { if (endYear == Number(this.year) && endMonth == Number(this .month)) { days = [...Array(endDay + 1).keys()].slice(startDay); } else { days = [...Array(totalDays + 1).keys()].slice(startDay); } } else if (endYear == Number(this.year) && endMonth == Number(this.month)) { days = [...Array(endDay + 1).keys()].slice(1); } else { days = [...Array(totalDays + 1).keys()].slice(1); } this.days = days this.generateArray('hour') } else if (type === 'hour') { let hours = [] if (startYear == Number(this.year) && startMonth == Number(this.month) && startDay == Number( this.day)) { if (endYear == Number(this.year) && endMonth == Number(this.month) && endDay == Number(this .day)) { hours = [...Array(endHour + 1).keys()].slice(startHour); } else { hours = [...Array(23 + 1).keys()].slice(startHour); } } else if (endYear == Number(this.year) && endMonth == Number(this.month) && endDay == Number( this.day)) { hours = [...Array(endHour + 1).keys()].slice(0); } else { hours = [...Array(23 + 1).keys()].slice(0); } this.hours = hours this.generateArray('minute') } else if (type === 'minute') { let minutes = [] if (startYear == Number(this.year) && startMonth == Number(this.month) && startDay == Number( this.day) && startHour == Number(this.hour)) { if (endYear == Number(this.year) && endMonth == Number(this.month) && endDay == Number(this.day) && endHour == Number(this.hour)) { minutes = [...Array(endMinute + 1).keys()].slice(startMinute); } else { minutes = [...Array(59 + 1).keys()].slice(startMinute); } } else if (endYear == Number(this.year) && endMonth == Number(this.month) && endDay == Number( this.day) && endHour == Number(this.hour)) { minutes = [...Array(endMinute + 1).keys()].slice(0); } else { minutes = [...Array(59 + 1).keys()].slice(0); } this.minutes = minutes this.generateArray('seconds') } else { let seconds = [] if (startYear == Number(this.year) && startMonth == Number(this.month) && startDay == Number( this.day) && startHour == Number(this.hour) && startMinute == Number(this.minute)) { if (endYear == Number(this.year) && endMonth == Number(this.month) && endDay == Number(this .day) && endHour == Number(this.hour) && endMinute == Number(this.minute)) { seconds = [...Array(endSecond + 1).keys()].slice(startSecond); } else { seconds = [...Array(59 + 1).keys()].slice(startSecond); } } else if (endYear == Number(this.year) && endMonth == Number(this.month) && endDay == Number(this .day) && endHour == Number(this.hour) && endMinute == Number( this.minute)) { seconds = [...Array(endSecond + 1).keys()].slice(0); } else { seconds = [...Array(59 + 1).keys()].slice(0); } this.seconds = seconds } }, close() { this.$emit('close') }, // 用户更改picker的列选项 change(e) { this.valueArr = e.detail.value; let i = 0; // 这里使用i++,是因为this.valueArr数组的长度是不确定长度的,它根据this.params的值来配置长度 // 进入if规则,i会加1,保证了能获取准确的值 if (this.params.year) { this.year = this.years[this.valueArr[i++]]; this.generateArray('year') } if (this.params.month) { this.month = this.months[this.valueArr[i++]]; this.generateArray('month') } if (this.params.day) { const index = this.valueArr[i++] this.day = this.days[index] ? this.days[index] : this.days[0]; this.generateArray('day') } if (this.params.hour) { this.hour = this.hours[this.valueArr[i++]]; this.generateArray('hour') } if (this.params.minute) { this.minute = this.minutes[this.valueArr[i++]]; this.generateArray('minute') } if (this.params.second) { this.second = this.seconds[this.valueArr[i++]]; this.generateArray('second') } }, // 用户点击确定按钮 getResult() { // #ifdef MP-WEIXIN if (this.moving) return; // #endif let result = {}; // 只返回用户在this.params中配置了为true的字段 if (this.params.year) result.year = this.formatNumber(this.year || 0); if (this.params.month) result.month = this.formatNumber(this.month || 0); if (this.params.day) result.day = this.formatNumber(this.day || 0); if (this.params.hour) result.hour = this.formatNumber(this.hour || 0); if (this.params.minute) result.minute = this.formatNumber(this.minute || 0); if (this.params.second) result.second = this.formatNumber(this.second || 0); if (this.params.timestamp) result.timestamp = this.getTimestamp(); this.$emit('confirm', result); this.close(); }, // 小于10前面补0,用于月份,日期,时分秒等 formatNumber(num) { return +num < 10 ? '0' + num : String(num); }, // 获取时间戳 getTimestamp() { let format = this.jnpf.handelFormat(this.format) let timeType = format === 'yyyy' ? '/01/01 00:00:00' : format === 'yyyy-MM' ? '/01 00:00:00' : format === 'yyyy-MM-dd' ? ' 00:00:00' : '' // yyyy-mm-dd为安卓写法,不支持iOS,需要使用"/"分隔,才能二者兼容 let time = ""; if (this.params.year && !this.params.month && !this.params.day && !this.params.hour && !this.params .minute && !this.params.second) { time = this.year + timeType } else if (this.params.year && this.params.month && !this.params.day && !this.params.hour && !this.params .minute && !this.params.second) { time = this.year + '/' + this.month + timeType } else if (this.params.year && this.params.month && this.params.day && !this.params.hour && !this.params .minute && !this.params.second) { time = this.year + '/' + this.month + '/' + this.day + timeType } else if (this.params.year && this.params.month && this.params.day && this.params.hour && !this.params .minute && !this.params.second) { time = this.year + '/' + this.month + '/' + this.day + " " + this.hour + timeType } else if (this.params.year && this.params.month && this.params.day && this.params.hour && this.params .minute && !this.params.second) { time = this.year + '/' + this.month + '/' + this.day + " " + this.hour + ":" + this.minute + timeType } else { time = this.year + '/' + this.month + '/' + this.day + " " + this.hour + ":" + this.minute + ":" + this .second + timeType } return new Date(time).getTime(); } } }; </script>

// 小于10前面补0,用于月份,日期,时分秒等 formatNumber(num) { return +num < 10 ? ‘0’ + num : String(num); }, // 获取时间戳 getTimestamp() { let format = this.jnpf.handelFormat(this.format) let timeType = format === ‘yyyy’ ? ‘/01/01 00:00:00’ : format === ‘yyyy-MM’ ? ‘/01 00:00:00’ : format === ‘yyyy-MM-dd’ ? ’ 00:00:00’ : ‘’ // yyyy-mm-dd为安卓写法,不支持iOS,需要使用"/"分隔,才能二者兼容 let time = “”; if (this.params.year && !this.params.month && !this.params.day && !this.params.hour && !this.params .minute && !this.params.second) { time = this.year + timeType } else if (this.params.year && this.params.month && !this.params.day && !this.params.hour && !this.params .minute && !this.params.second) { time = this.year + ‘/’ + this.month + timeType } else if (this.params.year && this.params.month && this.params.day && !this.params.hour && !this.params .minute && !this.params.second) { time = this.year + ‘/’ + this.month + ‘/’ + this.day + timeType } else if (this.params.year && this.params.month && this.params.day && this.params.hour && !this.params .minute && !this.params.second) { time = this.year + ‘/’ + this.month + ‘/’ + this.day + " " + this.hour + timeType } else if (this.params.year && this.params.month && this.params.day && this.params.hour && this.params .minute && !this.params.second) { time = this.year + ‘/’ + this.month + ‘/’ + this.day + " " + this.hour + “:” + this.minute + timeType } else { time = this.year + ‘/’ + this.month + ‘/’ + this.day + " " + this.hour + “:” + this.minute + “:” + this .second + timeType } return new Date(time).getTime(); }

在使用 uni-app 的富文本组件 editor 时,如果遇到无法正常使用的情况,可能是由于多种原因导致的。以下是一些常见的问题及其解决方法:

1. 平台兼容性问题

  • editor 组件在部分平台(如 H5、小程序)上可能存在兼容性问题。确保你使用的平台支持 editor 组件。
  • H5 端,editor 组件可能无法正常使用,建议使用 web-view 组件嵌入第三方富文本编辑器。

2. 版本问题

  • 确保你使用的 uni-app 版本是最新的,旧版本可能存在一些已知的 bug。
  • 更新 uni-app 到最新版本,或者检查是否有相关的 bug 修复。

3. 组件配置问题

  • 检查 editor 组件的配置是否正确。例如,placeholderread-only 等属性是否设置正确。
  • 确保 editor 组件的 id 是唯一的,避免与其他组件冲突。

4. 样式问题

  • editor 组件的样式可能会受到父组件样式的影响,导致显示异常。检查是否有样式冲突,并尝试重置 editor 组件的样式。

5. 事件绑定问题

  • 确保你正确绑定了 editor 组件的事件,如 inputfocusblur 等。事件处理函数中可能存在逻辑错误,导致组件无法正常工作。

6. 数据绑定问题

  • 如果使用 v-model 进行数据绑定,确保绑定的数据是响应式的,并且在数据变化时能够正确更新 editor 组件的内容。

7. 调试工具

  • 使用 uni-app 提供的调试工具(如 HBuilderX 的调试功能)来检查 editor 组件的运行状态,查看是否有错误信息输出。

8. 替代方案

  • 如果 editor 组件在特定平台上无法正常使用,可以考虑使用第三方富文本编辑器(如 wangEditorquill 等),并通过 web-view 组件嵌入到 uni-app 中。

示例代码

以下是一个简单的 editor 组件使用示例:

<template>
  <view>
    <editor
      id="myEditor"
      placeholder="请输入内容"
      @input="onInput"
      @focus="onFocus"
      @blur="onBlur"
    ></editor>
  </view>
</template>

<script>
export default {
  methods: {
    onInput(e) {
      console.log('输入内容:', e.detail.html);
    },
    onFocus() {
      console.log('编辑器获得焦点');
    },
    onBlur() {
      console.log('编辑器失去焦点');
    }
  }
};
</script>

<style>
/* 自定义样式 */
</style>
回到顶部