页面中用到了 uview 的 u--textarea 文本域组件,和常见文本输入框一样,如果被点击的位置已经有内容,则被点击的位置闪烁光标,如果被点击的位置还没有内容,则在内容结尾闪烁光标。同时,在文本域获取焦点后高度变小,给弹出的软键盘腾空位置。如下图:
如果点击的位置被包含在了文本域输入框变小后的展示区内,没有问题,但是如果点击的位置只被包含在。高度缩小前的展示区域,没有被包含在高度缩小后的展示区域,那么输入框缩小后光标就不会直接展示,需要手动滑动,或者是直接输入/删除字符后文本才会滚动到光标位置。
实际解决的时候遇到下面两个困难:
1 this.$refs
通过this.$refs 虽然可以获取到 u--textarea 组件,但是这个组件本身并没有提供滚动内容区和获取,设置光标位置的方法。
2 document.getElement...
通过浏览器查看发现 u--textarea 组件里封装的就是原生 textarea 并提供了一个类名“uni-textarea-textarea” 但是在 mounted 中 console.log(document) 直接输出 undefined 这里有个疑问,运行到APP 是没有 document 对象吗?为什么会是 undefined ?
3 通过 uniapp 官网找到了 uni.createSelectorQuery(),这个我看提供了几个 api 是可以获取各种信息,但好像就是没有提供 DOM 对象本身啊?!
4 我现在的思路是拿到 u--textarea 内部封装的 textarea 后就可以使用selection-start、selection-end、cursor、几个属性配合着失焦重新获得焦点就可以实现了,但是感觉非常二把刀,有没有更好的解决思路?
<template> <view class="body" ref='nihaoa'> <!-- 详情页 --> <text>姓名</text> <u--input placeholder="请输入内容" border="surround" v-model="nameInput"/> <text class="oop" id="oop">电话号码</text> <u--input placeholder="请输入内容" border="surround" v-model="numberInput"/> <text>详情</text> <u-textarea ref='' :maxlength="-1" v-model="msgInput" placeholder="请输入内容" :height="infoHeight" :adjust-position="false" /> </view></template><script>import {nanoid} from "nanoid" const { createClient } = require("webdav/dist/web"); export default { props:['showRow'], data() { return { // 列表数组本地缓存 "userlist":[], // 姓名输入框输入的内容 "nameInput":'', // 电话输入框输入的内容 "numberInput":'', // 详情文本框输入的内容 "msgInput":'', // 当前被编辑条目的key "key":'', // 数据被修改,是否保存,用于初次加载,避免保存修改使用 "saveFlg":false, // 键盘高度 "KeyboardHeight":0, } }, computed:{ infoHeight(){ if(this.KeyboardHeight){ return `30vh` }else{ return "70vh" } } }, watch:{ nameInput(){ this.chackSave() }, numberInput(){ this.chackSave() }, msgInput(){ this.chackSave() }, }, onLoad(queryy){ this.userlist=this.$store.state.customerList if(queryy.key=="undefined"){ this.saveFlg=true return } let timeObj=this.userlist.filter(item=>item.key==queryy.key)[0] this.key=timeObj.key this.nameInput=timeObj.name this.numberInput=timeObj.number this.msgInput=timeObj.msg this.$nextTick(()=>{ this.saveFlg=true }) }, mounted(){ // console.log(document) uni.onKeyboardHeightChange(this.keyBarEvent) }, beforeDestroy(){ uni.offKeyboardHeightChange(this.keyBarEvent) }, methods: { // 键盘高度变化方法 keyBarEvent(event){ // uni-textarea-textarea console.log('键盘高度变了') this.KeyboardHeight=event.height setTimeout(()=>{ console.log('?????????????????????????????????????') console.log(this.$refs.nihaoa) // const query = uni.createSelectorQuery().in(this); // let timeObj=query.select('oop') // console.log(timeObj) // const query = uni.createSelectorQuery().in(this); // let timeObj=query.select('.uni-textarea-textarea') // console.log(timeObj.selectionStart) },2000) }, // 检查是否对数据进行保存并持久化 chackSave(){ if(this.saveFlg){ this.save() this.$store.dispatch('writeToFile') } }, save(){ // 将当前内容封装为对象 const timeobj={ "key":this.key, "name":this.nameInput, "number":this.numberInput, "msg":this.msgInput } // 标识是否有输入内容 const flg=this.nameInput.trim()!="" || this.numberInput.trim()!="" || this.msgInput.trim()!=""?true:false // 修改老人数据(有输入内容,且有对应的key) if(flg && this.key!=''){ this.userlist=this.userlist.filter(item=>item.key!=this.key) this.userlist.unshift(timeobj) } // 删除一个人的数据(有对应的key,但是没有输入数据) else if(!flg && this.key!=''){ this.userlist=this.userlist.filter((item)=>item.key!=this.key) } // 添加一个人的数据(有输入的内容,但没有输入的key) else if(flg && this.key==''){ this.key=nanoid() timeobj.key=this.key this.userlist.unshift(timeobj) } this.$store.commit('SET_CUSTOMER_LIST',this.userlist) }, }, }</script><style scoped>.body{ padding: 20rpx; height: 100vh; box-sizing: border-box; position: relative; overflow: hidden;}.addButton{ position: absolute; z-index: 99; right: 20rpx; bottom: 25rpx; border-radius: 50%;}</style>
手搓一个:
<!-- my-textarea.vue --><template> <view> <textarea class="uni-textarea-textarea" ref="textarea" v-model="value" @input="onInput" /> </view></template><script>export default { props: ['value'], methods: { onInput(e) { this.$emit('input', e.target.value); }, setCursorPosition(position) { const textarea = this.$refs.textarea; if (textarea) { textarea.selectionStart = position; textarea.selectionEnd = position; } } }};</script>
父组件里用ref 拿到my-textarea 组件的实例:
<template> <view class="body"> <!-- 其他代码 --> <my-textarea ref="myTextarea" v-model="msgInput" :height="infoHeight" :adjust-position="false" /> </view></template><script>import MyTextarea from './my-textarea.vue';export default { components: { 'my-textarea': MyTextarea }, methods: { keyBarEvent(event) { console.log('键盘高度变了'); this.KeyboardHeight = event.height; setTimeout(() => { const query = uni.createSelectorQuery().in(this); query.select('.uni-textarea-textarea').boundingClientRect(); query.exec((res) => { const cursorPosition = this.calculateCursorPosition(res[0]); this.$refs.myTextarea.setCursorPosition(cursorPosition); }); }, 2000); }, calculateCursorPosition(rect) { // 根据文本的位置和尺寸信息计算光标应该在哪个位置 // 看实际需求进行计算 return 0; // 返回值 } }};</script>
本文向大家介绍vue怎么获取DOM节点?相关面试题,主要包含被问及vue怎么获取DOM节点?时的应答技巧和注意事项,需要的朋友参考一下
pages.json 中 pages配置四个页面,其中有三个配置到了tabBar中 删减代码如下: 我现在需要从客户通讯录中通过点击跳转到没有配置在tabBar中的 客户详情页面中,事件代码如下: 结果控制台报错: 我的文件 '/pages/CustomerInfo/index' 是存在的,路径也没有写错,为什么会找不到页面呢?
扩展package.json不支持app区分环境,有什么方法可以实现类似的吗?目前想要通过不同打包命令,区分环境
小程序下 想把 uniapp中默认的导航栏的返回按钮去掉
config.js里怎么配置,配置好后又怎么知道打的包是开发环境的包还是生产环境的包? app是不是不能打包?有人试过么?