uniapp 开发安卓APP 一般怎么获取DOM节点?

场景:

页面中用到了 uview 的 u--textarea 文本域组件,和常见文本输入框一样,如果被点击的位置已经有内容,则被点击的位置闪烁光标,如果被点击的位置还没有内容,则在内容结尾闪烁光标。同时,在文本域获取焦点后高度变小,给弹出的软键盘腾空位置。如下图:

uniapp 开发安卓APP 一般怎么获取DOM节点?
uniapp 开发安卓APP 一般怎么获取DOM节点?

问题:

如果点击的位置被包含在了文本域输入框变小后的展示区内,没有问题,但是如果点击的位置只被包含在。高度缩小前的展示区域,没有被包含在高度缩小后的展示区域,那么输入框缩小后光标就不会直接展示,需要手动滑动,或者是直接输入/删除字符后文本才会滚动到光标位置。

实际解决的时候遇到下面两个困难:

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>

以上是 uniapp 开发安卓APP 一般怎么获取DOM节点? 的全部内容, 来源链接: utcz.com/p/934794.html

回到顶部