簡體   English   中英

如何在 JavaScript/Vue 的文本字段中獲取插入符號的當前 position?

[英]How do I get the current position of the caret in a text-field in JavaScript/Vue?

我正在嘗試對文本字段進行少量的生活質量更改,以允許用戶在美分已滿時更改文本字段的美元金額。

目前,我的字段將 append 基於用戶移動到另一個字段時輸入的內容(觸發@blur事件)的十進制數量。

  • 1將變為1.00
  • 1.將變為1.00
  • 1.5將變為1.50

我對其進行編碼的方式是檢查該字段是否與正則表達式匹配( /((\d*\.){1}(\d{2}))/ )以查看該字段是否“已滿”。 如果是這樣,我想獲取用戶的插入符號/光標/插入點/無論是什么術語,以檢查它是在小數點之前還是之后。

  • 如果它在小數點之前,即100|.00 ,我希望他們能夠輸入更多數字。
  • 如果它在小數點之后,即100.|00 ,我希望他們能夠輸入更多的數字。

這聽起來像是refsselectionStart/selectionEnd的工作,你幾乎是對的(而且你可能仍然是)。 即使在 Google 刪除了type="number"字段的該功能之后,也有使用這些屬性的解決方法。 我看過許多不同的帖子,其中一些可以追溯到近 13 年前。 不過,我似乎無法讓它正常工作。

這是我所擁有的:


模板標簽

<v-container>
    <v-row v-for="(exp, index) in travelExpenseArray" :key="exp.id" style="margin-top: -20px;" >
        <v-col v-show="$vuetify.breakpoint.smAndUp" cols="auto" sm="2" />
        <v-col cols="auto" sm="4" >
            <v-checkbox  v-model="exp.checked" :label="exp.title" dense @change="checkEnabled(index, exp.checked)"/>
        </v-col>
        <v-col cols="auto" sm="4">
            <v-card-text style="padding: 0px;">{{exp.title}} Expenses</v-card-text>
            <v-text-field :ref="`vtf${index}`" outlined step=".01" v-model="exp.expense" type="number" hide-details
            dense single-line :disabled="!exp.checked" hide-spin-buttons @keypress="checkValidKey($event, index)" 
            @click="clearCurrencyField(index)" @blur="appendZeros(index)"/>
        </v-col>
        <v-col v-show="$vuetify.breakpoint.smAndUp" cols="auto" sm="2" />
    </v-row>

    <v-row style="margin-top: -20px;">
        <v-col cols="auto" sm="6" />
        <v-col cols="auto" sm="4">
            <v-card-text style="padding: 0px">Total Travel Expenses</v-card-text>
            <v-text-field outlined v-model="totalTravelExpenses" dense disabled />
        </v-col>
        <v-col v-show="$vuetify.breakpoint.smAndUp" cols="auto" sm="2" />
    </v-row>
</v-container>

分解它:我有一個旅行費用數組,我循環並動態創建文本字段, v-model將數組中的值與文本字段中的值相匹配。 幸運的是,我能夠創建動態ref=''屬性,這將在腳本部分派上用場。


腳本標簽

(特別是發生這種情況的 checkValidKey 方法)

checkValidKey(evt, index){
    let expense = this.travelExpenseArray[index].expense;               
    // Get the key code from the event.
    const charCode = evt.which ? evt.which : evt.keyCode;

    // Ensure key is a valid key ('0-9.' and numpad '0-9.').
    // Prevent if there's no match.
    if(!this.getValidKeys().includes(charCode)){
        evt.preventDefault();

    // okay so this block checks the expense against the regex
    // if it matches, (tentatively) prevent the key press 
    // because a 'full' cost has been entered.
    }else if((/((\d*\.){1}(\d{2}))/).test(expense)){

        // chrome removed this functionality for `type = "number"` fields in 2014 or so
        this.$refs[`vtf${index}`][0].$refs.input.type = "text";
        console.log(this.$refs[`vtf${index}`][0].$refs.input.selectionStart);
        // not typing all that out over and over
        let selection = {
            start: this.$refs[`vtf${index}`][0].$refs.input.selectionStart,
            end: this.$refs[`vtf${index}`][0].$refs.input.selectionEnd
        }
                    
        // check if the cursor is in a valid position
        if(selection.start >= selection.end - 2){
            evt.preventDefault();
        }
        // should probably do this to be safe; this seems like
        // a really hacky solution to such a negligible problem
        this.$refs[`vtf${index}`][0].$refs.input.type = "number";
                    
        return;
    }
},

評論說同樣的話,但首先我得到按下的鍵的值。 如果它不在有效鍵列表中,請忽略按下。 如果是,並且該字段的值與正則表達式匹配,我會通過它的$ref獲得該字段,並帶有一點我覺得不應該工作的黑魔法,但我認為自己很幸運,它確實如此。 我將類型轉換為文本以允許我使用selectionStartselectionEnd ,然后我將應該是起點和終點的內容存儲在 object 中以做一些速記。 我做了一個比較,如果它通過了,我會阻止密鑰注冊。 然后我將字段類型轉換回數字並返回。

另外,如果有用的話,這里是費用在 vuex 商店中的結構:

travelExpenseArray: [
    {id: 0, title: 'Bus', checked: false, expense: '0.00'},
    {id: 1, title: 'Car', checked: false, expense: '0.00'},
    {id: 2, title: 'Plane', checked: false, expense: '0.00'},
    {id: 3, title: 'Train', checked: false, expense: '0.00'},
],

我遇到的問題是,由於某種原因, selectionStartselectionEnd都出現為0 我知道這可能是因為實際上沒有選擇任何文本,但是沒有getCaretPosition方法或caretPosition屬性。 我真的很喜歡這種解決方法......工作,但我也不想繼續浪費時間希望它不會這樣做。

所以我所做的事情很容易完成(甚至更多),只需安裝一個庫而不是重新發明輪子。

我剛剛用npm install v-money v-money

應用程序.vue


添加了以下幾行:

import money from 'v-money';
Vue.use(money);

TravelExpenseForm.vue

(使用此方法的組件)


修改了v-text-field以包含v-money="money"指令。

在數據選項中添加了以下 object:

money: {
    decimal: '.',
    thousands: ',',
    prefix: '$',
    suffix: '',
    precision: 2
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM