Compose 没有 inputType 怎么过滤(限制)输入内容?这题我会!

这篇具有很好参考价值的文章主要介绍了Compose 没有 inputType 怎么过滤(限制)输入内容?这题我会!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

闲话

在我之前的文章 《Compose For Desktop 实践:使用 Compose-jb 做一个时间水印助手》 中,我埋了一个坑,关于在 Compose 中如何过滤 TextField 的输入内容。时隔好几个月了,今天这篇文章就是来填这个坑的。

为什么需要添加过滤

在正式开始之前,我们先来回答一下标题这个问题,为什么需要过滤呢?

众所周知,在安卓的原生 View 体系中,输入框是 EditText 我们可以通过在 xml 布局文件中添加 inputType 属性来指定预设的几个允许的输入内容格式,例如:numbernumberDecimalnumberSigned 等属性,分别表示过滤输入结果仅允许输入数字、十进制数字、带符号数字。另外,我们也可以通过给 EditText 自定义继承自 InputFilter 的过滤方法(setFilters)来自定义我们自己的过滤规则。

但是在 Compose 中我们应该怎么去做呢?

在 Compose 中,输入框是 TextField,查遍 TextField 的参数列表,我们就会发现,并没有给我们提供任何类似于 EditText 的过滤参数。

最多只能找到一个 keyboardOptions: KeyboardOptions = KeyboardOptions.Default 参数,而这个参数也只是请求输入法展示我们要求的输入类型,例如只展示数字键盘,但是,这里只是请求,并不是要求,所以人家输入法还不一定理呢,哈哈哈。而且这个参数并不能限制输入框的内容,只是更改了默认弹出软键盘的类型而已。

其实想想也不难理解,毕竟 Compose 是声明式 UI ,如何处理输入内容确实应该由我们自己来实现。

但是如果官方能提供几个类似 EditText 的预设过滤参数就好了,可惜并没有。

所以我们需要自己实现对输入内容的过滤。

回到标题内容,为什么我们需要过滤输入内容?

这里我们将以上文中中提到的 时间水印助手 为例子讲解:

Compose 没有 inputType 怎么过滤(限制)输入内容?这题我会!

在这个界面中,我们需要输入多个参数。

比如参数 “导出图像质量” ,我们需要将输入内容限制在 0.0 - 1.0 的浮点数。

当然,我们完全可以不在输入时限制,可以允许用户随意输入任意内容,然后在实际提交数据时再做校验,但是,显然,这样是不合理的,用户体验也不佳。

所以我们最好还是能直接在用户输入时就做好限制。

实现

先简单试一下

其实想做过滤也不是不行,想想好像还是挺简单的嘛,这里以简单的限制输入内容长度(类似 EditTExt 中的 maxLength 属性)为例子举例:

var inputValue by remember { mutableStateOf("") }

TextField(
    value = inputValue,
    onValueChange = { inputValue = it }
)

可能读者们会说,嗨,不就是限制输入长度嘛,这在声明式 UI 中都不叫事,看我直接这样就行了:

val maxLength = 8
var inputValue by remember { mutableStateOf("") }

TextField(
    value = inputValue,
    onValueChange = {
        if (it.length <= maxLength) inputValue = it
    }
)

我们在输入值改变时加一个判断,只有输入值的长度小于了定义的最大长度我们才改变 inputValue 的值。

咋一看,好想没有问题是吧?

但是,你再仔细想想。

真的这么简单吗?

你有没有想过以下两种情况:

  1. 我们在已经输入了 8 个字符后,把光标移动到中间位置,此时再输入内容,你猜会发生什么?
  2. 我们在输入了不足8个的字符(例如 5 个后),同时粘贴超过限制字符数的内容(例如 4 个),你猜会发生什么?

不卖关子了,其实对于 情况 1 ,会出现内容确实没有继续添加了,但是光标会往后走的情况:

Compose 没有 inputType 怎么过滤(限制)输入内容?这题我会!

而对于 情况 2 ,相信不用我说,读者也能猜出来了,那就是粘贴后没有任何反应。

没错,显然因为我们在 onValueChange 中加了判断,如果当前输入的值 (it) 大于了限制的值(maxLength )那么我们将不会做任何响应。但是这个显然是不合理的,因为虽然我们粘贴的所有内容直接插入输入框的话确实会超出最大字符限制,但是并不是说输入框不能再输入内容了,很显然,输入框还可以接受再输入 3 个字符。所以我们应该做的处理是将新输入的内容截断,截取符合数量的内容插入输入框,多余的内容直接舍弃。

原生 View 的 EditText 也是这样的处理逻辑。

那么,现在我们应该怎么做呢?

实践一下,限制输入字符长度

经过上面的小试牛刀,相信大家也知道了,对于限制输入内容,不能简单的直接对输入的 String 做处理,而应该考虑到更多的情况,其中最需要关注的情况有两点:一是对输入框光标的控制;二是对选择多个字符和粘贴多个字符情况的处理(因为正常输入可以保证每次只输入(或删除)一个字符,但是粘贴或多选后不一定)。

很显然,如果想控制光标的话,我们不能直接使用 value 为 String 的 TextField 而应该改用使用 TextFieldValue

var inputValue by remember { mutableStateOf(TextFieldValue()) }

OutlinedTextField(
    value = inputValue,
    onValueChange = {  }
)

TextFieldValue 是一个封装了输入内容(text: String)、和选择以及光标状态(selection: TextRange)的类。

其中 TextRange 有两个参数 startend 分别表示选中文本时的开始和结束位置,如果两个值相等则表示没有选中任何文本,此时 TextRange 表示的是光标位置。

现在,我们已经具备了可以解决上面说的两点问题的前置条件,下面就是应该怎么去解决这个问题了。

其实对于问题 1 ,非常好解决,我们甚至都不需要过多的去变动代码,只需要把使用的 String 值 改成 TextFieldValue 即可:

val maxLength = 8
var inputValue by remember { mutableStateOf(TextFieldValue()) }

OutlinedTextField(
    value = inputValue,
    onValueChange = {
        if (it.text.length <= maxLength) inputValue = it
    }
)

原因也很简单,因为 TextFieldValue 中已经包含了光标信息,这里我们在输入内容超过限制长度时不做更改 inputValue 的值,实际上是连同光标信息一起不做更改了,而上面直接使用的是 String ,则只是不改变输入内容,但是光标位置还是会被改变。

而对于问题 2 ,需要我们做一些特殊的处理。

我们首先定义一个函数来处理输入内容的改动:

fun filterMaxLength(
    inputTextField: TextFieldValue,
    lastTextField: TextFieldValue,
    maxLength: Int
): TextFieldValue {
    // TODO
}

这个函数接收两个参数:inputTextFieldlastTextField 分别表示加上新输入的内容后的 TextFieldValue 和没有输入新内容时的 TextFieldValue

这里有个地方需要注意,就是在 TextFieldonChange 回调中,如果使用的是 TextFieldValue,那么不仅会在输入内容发生改变时才调用 onChange 回调,而是即使只有光标的移动或状态改变都会调用 onChange 回调。

然后,我们在这个函数中处理一下对于粘贴多个字符时的情况:

val inputCharCount = inputTextField.text.length - lastTextField.text.length
if (inputCharCount > 1) { // 同时粘贴了多个字符内容
    val allowCount = maxLength - lastTextField.text.length
    // 允许再输入字符已经为空,则直接返回原数据
    if (allowCount <= 0) return lastTextField

    // 还有允许输入的字符,则将其截断后插入
    val newString = StringBuffer()
    newString.append(lastTextField.text)
    val newChar = inputTextField.text.substring(lastTextField.selection.start..allowCount)
    newString.insert(lastTextField.selection.start, newChar)
    return lastTextField.copy(text = newString.toString(), selection = TextRange(lastTextField.selection.start + newChar.length))
}

这段代码其实很好理解,首先我们通过使用未更新前的字符长度减去本次输入的字符长度得到本次实际新增的字符长度,如果这个长度大于 1 则认为是同时粘贴了多个内容进输入框。(这里有个点需要注意,就是这样得到的值可能会等于 0,表示只是光标的变动,字符没有变;小于 0 ,表示是删除内容。)

然后再使用最大允许输入的字符长度减去未更新前的输入框字符长度,即可得到当前还允许再插入多少个字符 allowCount

如果尚还余有可输入的字符,则通过截取输入内容字符的符合长度的新增字段来获取。

截取的起点使用的是未更新前的光标起始位置(lastTextField.selection.start),截取长度就是还允许输入的字符长度。

需要注意的是,这里之所以使用 lastTextField.selection.start 作为截取起点,而不是 lastTextField.selection.end 是因为粘贴插入时也可能是因为之前已经选中了部分内容,然后再插入的,此时就应该以 未更新时的选中状态起点 作为插入的位置。而如果粘贴插入时并非选中状态,那么使用 startend 都可以,因为此时它俩的值是一样的。

拿到可以插入的字符后,接下里就是将其插入即可:newString.insert(lastTextField.selection.start, newChar)

最后返回时别忘了改一下光标的位置,这里其实也很简单,就是改到新字符插入的位置+实际插入的字符数量: TextRange(lastTextField.selection.start + newChar.length)

最后,完整的限制输入长度的过滤函数如下:

/**
 * 过滤输入内容长度
 *
 * @param maxLength 允许输入长度,如果 小于 0 则不做过滤,直接返回原数据
 * */
fun filterMaxLength(
    inputTextField: TextFieldValue,
    lastTextField: TextFieldValue,
    maxLength: Int
): TextFieldValue {
    if (maxLength < 0) return inputTextField // 错误的长度,不处理直接返回

    if (inputTextField.text.length <= maxLength) return inputTextField // 总计输入内容没有超出长度限制


    // 输入内容超出了长度限制
    // 这里要分两种情况:
    // 1. 直接输入的,则返回原数据即可
    // 2. 粘贴后会导致长度超出,此时可能还可以输入部分字符,所以需要判断后截断输入

    val inputCharCount = inputTextField.text.length - lastTextField.text.length
    if (inputCharCount > 1) { // 同时粘贴了多个字符内容
        val allowCount = maxLength - lastTextField.text.length
        // 允许再输入字符已经为空,则直接返回原数据
        if (allowCount <= 0) return lastTextField

        // 还有允许输入的字符,则将其截断后插入
        val newString = StringBuffer()
        newString.append(lastTextField.text)
        val newChar = inputTextField.text.substring(lastTextField.selection.start..allowCount)
        newString.insert(lastTextField.selection.start, newChar)
        return lastTextField.copy(text = newString.toString(), selection = TextRange(lastTextField.selection.start + newChar.length))
    }
    else { // 正常输入
        return if (inputTextField.selection.collapsed) { // 如果当前不是选中状态,则使用上次输入的光标位置,如果使用本次的位置,光标位置会 +1
            lastTextField
        } else { // 如果当前是选中状态,则使用当前的光标位置
            lastTextField.copy(selection = inputTextField.selection)
        }
    }
}

其实这里的过滤函数还是有问题,不知道读者是否发现了?这里我就不指出也不改了,权当是留给读者们的一个思考题了,哈哈,毕竟不希望读者只是草草看完直接把代码粘贴走就完事了,哈哈哈哈。

我们在使用的时候只需要改一下 TextFieldonChange 回调即可:

val maxLength = 8
var inputValue by remember { mutableStateOf(TextFieldValue()) }
OutlinedTextField(
    value = inputValue,
    onValueChange = {
        inputValue = filterMaxLength(it, inputValue, maxLength)
    }
)

扩展一下,做一个通用的过滤

虽然上面我们已经实现了做一个自己的输入内容限制,但是似乎扩展性不怎么好啊。

我们有没有办法做一个通用的,方便扩展的过滤方法呢?

毕竟 View 中的过滤不仅是自己预设了很多好用的过滤,而且它还提供了一个通用的接口 InputFilter 可以让我们自己定义我们自己需要的过滤方法。

那么,说干就干,首先我们来看看 View 中的 InputFilter 是怎么写的:

Compose 没有 inputType 怎么过滤(限制)输入内容?这题我会!

这么一看,其实也不是很复杂,就是一个 InputFilter 类,只有一个 filter 方法,这个方法返回一个 CharSequence 表示经过过滤处理后的新的字符。

它提供了 6 个参数:

  1. source :要插入的新字符
  2. startsource 中要插入的字符位置起点
  3. endsource 中要插入的字符位置终点
  4. dest : 输入框中的原内容
  5. dstartdest 中要被 source 插入的位置的起点
  6. denddest 中要被 source 插入的位置的终点

我们只需要使用这六个参数对字符进行过滤处理后返回新的字符就可以了。

但是 View 中的 InputFilter 显然只负责过滤字符,不负责处理更改光标的位置。

不管怎样,我们也照猫画虎做一个 Compose 版本的过滤基类 BaseFieldFilter

open class BaseFieldFilter {
    private var inputValue = mutableStateOf(TextFieldValue())

    protected open fun onFilter(inputTextFieldValue: TextFieldValue, lastTextFieldValue: TextFieldValue): TextFieldValue {
        return TextFieldValue()
    }

    protected open fun computePos(): Int {
        // TODO
        return 0
    }

    protecte fun getNewTextRange(
        lastTextFiled: TextFieldValue,
        inputTextFieldValue: TextFieldValue
    ): TextRange? {
        // TODO
        retutn null
    }

    protecte fun getNewText(
        lastTextFiled: TextFieldValue,
        inputTextFieldValue: TextFieldValue
    ): TextRange? {
        // TODO
        return null
    }

    fun getInputValue(): TextFieldValue {
        return inputValue.value
    }

    fun onValueChange(): (TextFieldValue) -> Unit {
        return {
            inputValue.value = onFilter(it, inputValue.value)
        }
    }
}

在这类中我们需要重点关注 onFilter 方法,我们的过滤内容主要在这个方法中编写。

然后在 TextField 中主要会使用到 getInputValueonValueChange 方法。

本来我还打算写几个基础的工具方法 getNewTextgetNewTextRangecomputePos 分别用于计算实际插入的新字符、实际插入字符的位置、新的索引位置。

但是后来发现似乎并不好写出一个很好用的通用方法,所以这里我就留空了。

这个基础类使用起来也很简单,我们只需要将我们自己的过滤方法继承这个基础类,然后重载 onFilter 方法即可,还是以限制输入长度为例,写一个类 FilterMaxLength

/**
 * 过滤输入内容长度
 *
 * @param maxLength 允许输入长度,如果 小于 0 则不做过滤,直接返回原数据
 * */
class FilterMaxLength(
    @androidx.annotation.IntRange(from = 0L)
    private val maxLength: Int
) : BaseFieldFilter() {
    override fun onFilter(
        inputTextFieldValue: TextFieldValue,
        lastTextFieldValue: TextFieldValue
    ): TextFieldValue {
        return filterMaxLength(inputTextFieldValue, lastTextFieldValue, maxLength)
    }

    private fun filterMaxLength(
        inputTextField: TextFieldValue,
        lastTextField: TextFieldValue,
        maxLength: Int
    ): TextFieldValue {
        if (maxLength < 0) return inputTextField // 错误的长度,不处理直接返回

        if (inputTextField.text.length <= maxLength) return inputTextField // 总计输入内容没有超出长度限制


        // 输入内容超出了长度限制
        // 这里要分两种情况:
        // 1. 直接输入的,则返回原数据即可
        // 2. 粘贴后会导致长度超出,此时可能还可以输入部分字符,所以需要判断后截断输入

        val inputCharCount = inputTextField.text.length - lastTextField.text.length
        if (inputCharCount > 1) { // 同时粘贴了多个字符内容
            val allowCount = maxLength - lastTextField.text.length
            // 允许再输入字符已经为空,则直接返回原数据
            if (allowCount <= 0) return lastTextField

            // 还有允许输入的字符,则将其截断后插入
            val newString = StringBuffer()
            newString.append(lastTextField.text)
            val newChar = inputTextField.text.substring(lastTextField.selection.start..allowCount)
            newString.insert(lastTextField.selection.start, newChar)
            return lastTextField.copy(text = newString.toString(), selection = TextRange(lastTextField.selection.start + newChar.length))
        }
        else { // 正常输入
            return if (inputTextField.selection.collapsed) { // 如果当前不是选中状态,则使用上次输入的光标位置,如果使用本次的位置,光标位置会 +1
                lastTextField
            } else { // 如果当前是选中状态,则使用当前的光标位置
                lastTextField.copy(selection = inputTextField.selection)
            }
        }
    }
}

此时,我们在 TextField 中只需要这样即可调用:

val filter = remember { FilterMaxLength(8) }
    
OutlinedTextField(
    value = filter.getInputValue(),
    onValueChange = filter.onValueChange(),
)

怎么样,是不是非常的方便快捷?

我还想要更多!

当然,上面一直都是拿的限制输入长度举例子,那其他的过滤实现呢?你倒是端出来啊,别急,这就为各位奉上我项目中用到的几个过滤方法。

同样的,这些方法或多或少我都留有坑,各位千万不要不检查一下直接就用哦(坏笑)。

哈哈哈,开玩笑了,其实完整没坑的代码各位可以去前言中我提到的那个项目中找。

过滤数字

class FilterNumber(
    private val minValue: Double = -Double.MAX_VALUE,
    private val maxValue: Double = Double.MAX_VALUE,
    private val decimalNumber: Int = -1
) : BaseFieldFilter() {

    override fun onFilter(
        inputTextFieldValue: TextFieldValue,
        lastTextFieldValue: TextFieldValue
    ): TextFieldValue {
        return filterInputNumber(inputTextFieldValue, lastTextFieldValue, minValue, maxValue, decimalNumber)
    }

    private fun filterInputNumber(
        inputTextFieldValue: TextFieldValue,
        lastInputTextFieldValue: TextFieldValue,
        minValue: Double = -Double.MAX_VALUE,
        maxValue: Double = Double.MAX_VALUE,
        decimalNumber: Int = -1,
    ): TextFieldValue {
        val inputString = inputTextFieldValue.text
        val lastString = lastInputTextFieldValue.text

        val newString = StringBuffer()
        val supportNegative = minValue < 0
        var dotIndex = -1
        var isNegative = false

        if (supportNegative && inputString.isNotEmpty() && inputString.first() == '-') {
            isNegative = true
            newString.append('-')
        }

        for (c in inputString) {
            when (c) {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' -> {
                    newString.append(c)
                    val tempValue = newString.toString().toDouble()
                    if (tempValue > maxValue) newString.deleteCharAt(newString.lastIndex)
                    if (tempValue < minValue) newString.deleteCharAt(newString.lastIndex) // TODO 需要改进 (例如限制最小值为 100000000,则将无法输入东西)

                    if (dotIndex != -1) {
                        if (decimalNumber != -1) {
                            val decimalCount = (newString.length - dotIndex - 1).coerceAtLeast(0)
                            if (decimalCount > decimalNumber) newString.deleteCharAt(newString.lastIndex)
                        }
                    }
                }
                '.' -> {
                    if (decimalNumber != 0) {
                        if (dotIndex == -1) {
                            if (newString.isEmpty()) {
                                if (abs(minValue) < 1) {
                                    newString.append("0.")
                                    dotIndex = newString.lastIndex
                                }
                            } else {
                                newString.append(c)
                                dotIndex = newString.lastIndex
                            }

                            if (newString.isNotEmpty() && newString.toString().toDouble() == maxValue) {
                                dotIndex = -1
                                newString.deleteCharAt(newString.lastIndex)
                            }
                        }
                    }
                }
            }
        }

        val textRange: TextRange
        if (inputTextFieldValue.selection.collapsed) { // 表示的是光标范围
            if (inputTextFieldValue.selection.end != inputTextFieldValue.text.length) { // 光标没有指向末尾
                var newPosition = inputTextFieldValue.selection.end + (newString.length - inputString.length)
                if (newPosition < 0) {
                    newPosition = inputTextFieldValue.selection.end
                }
                textRange = TextRange(newPosition)
            }
            else { // 光标指向了末尾
                textRange = TextRange(newString.length)
            }
        }
        else {
            textRange = TextRange(newString.length)
        }

        return lastInputTextFieldValue.copy(
            text = newString.toString(),
            selection = textRange
        )
    }
}

仅允许输入指定字符

class FilterOnlyChar() : BaseFieldFilter() {
    private var allowSet: Set<Char> = emptySet()

    constructor(allowSet: String) : this() {
        val tempSet = mutableSetOf<Char>()
        for (c in allowSet) {
            tempSet.add(c)
        }
        this.allowSet = tempSet
    }

    constructor(allowSet: Set<Char>) : this() {
        this.allowSet = allowSet
    }

    override fun onFilter(
        inputTextFieldValue: TextFieldValue,
        lastTextFieldValue: TextFieldValue
    ): TextFieldValue {
        return filterOnlyChar(
            inputTextFieldValue,
            lastTextFieldValue,
            allowChar = allowSet
        )
    }

    private fun filterOnlyChar(
        inputTextFiled: TextFieldValue,
        lastTextFiled: TextFieldValue,
        allowChar: Set<Char>
    ): TextFieldValue {
        if (allowChar.isEmpty()) return inputTextFiled // 如果允许列表为空则不过滤

        val newString = StringBuilder()

        var modifierEnd = 0

        for (c in inputTextFiled.text) {
            if (c in allowChar) {
                newString.append(c)
            }
            else modifierEnd--
        }

        return inputTextFiled.copy(text = newString.toString())
    }
}

过滤电子邮箱地址

class FilterStandardEmail(private val extraChar: String = "") : BaseFieldFilter() {
    private val allowChar: MutableSet<Char> = mutableSetOf('@', '.', '_', '-').apply {
        addAll('0'..'9')
        addAll('a'..'z')
        addAll('A'..'Z')
        addAll(extraChar.asIterable())
    }

    override fun onFilter(
        inputTextFieldValue: TextFieldValue,
        lastTextFieldValue: TextFieldValue
    ): TextFieldValue {
        return inputTextFieldValue.copy(text = filterStandardEmail(inputTextFieldValue.text, lastTextFieldValue.text))
    }

    private fun filterStandardEmail(
        inputString: String,
        lastString: String,
    ): String {
        val newString = StringBuffer()
        var flag = 0 // 0 -> None 1 -> "@" 2 -> "."

        for (c in inputString) {
            if (c !in allowChar) continue

            when (c) {
                '@' -> {
                    if (flag == 0) {
                        if (newString.isNotEmpty() && newString.last() != '.') {
                            if (newString.isNotEmpty()) {
                                newString.append(c)
                                flag++
                            }
                        }
                    }
                }
                '.' -> {
                    // if (flag >= 1) {
                        if (newString.isNotEmpty() && newString.last() != '@' && newString.last() != '.') {
                            newString.append(c)
                            // flag++
                        }
                    // }
                }
                else -> {
                    newString.append(c)
                }
            }
        }

        return newString.toString()
    }

}

过滤十六进制颜色

class FilterColorHex(
    private val includeAlpha: Boolean = true
) : BaseFieldFilter() {

    override fun onFilter(
        inputTextFieldValue: TextFieldValue,
        lastTextFieldValue: TextFieldValue
    ): TextFieldValue {
        return inputTextFieldValue.copy(filterInputColorHex(
            inputTextFieldValue.text,
            lastTextFieldValue.text,
            includeAlpha
        ))
    }

    private fun filterInputColorHex(
        inputValue: String,
        lastValue: String,
        includeAlpha: Boolean = true
    ): String {
        val maxIndex = if (includeAlpha) 8 else 6
        val newString = StringBuffer()
        var index = 0

        for (c in inputValue) {
            if (index > maxIndex) break

            if (index == 0) {
                if (c == '#') {
                    newString.append(c)
                    index++
                }
            }
            else {
                if (c in '0'..'9' || c.uppercase() in "A".."F" ) {
                    newString.append(c.uppercase())
                    index++
                }
            }
        }

        return newString.toString()
    }
}

总结

虽然在 Compsoe 中官方没有提供类似于 EditText 中的 inputType 的预设输入内容过滤,但是得益于 Compose 的声明式 UI,在 Compose 中过滤输入内容更加简单,都不需要太多繁琐的步骤,因为我们可以直接操作输入的内容。

本文就由浅入深的介绍了如何在 Compose 中快速实现类似于安卓原生 View 中的 inputType 输入内容过滤的方法,并且提供了几种常用的过滤供大家使用。文章来源地址https://www.toymoban.com/news/detail-461189.html

到了这里,关于Compose 没有 inputType 怎么过滤(限制)输入内容?这题我会!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Docker Compose资源限制

    Docker Compose资源限制

       防止容器占用过多资源,影响其他容器或宿主机 保证容器稳定运行,避免OOM等情况. OOM现象 :根据优先机制kill掉宿主机上最高的进程从而来释放空间,只要是宿主机的进程都可能被kill掉的。 进行资源隔离,提高安全性 使用docker-compose文件部署PostgreSQL,并设置资源限制。 1

    2024年02月15日
    浏览(9)
  • input限制只能输入数字,限制输入数字长度或者大小

    input限制只能输入数字,限制输入数字长度或者大小

    1.限制只能输入数字 方式一 :此方式只能控制输入的内容是数字,不能控制是否是正负数 方式二 :此方式可控制输入的内容是数字 了解一下 js replace : 拓展 1.限制输入的数字长4位 了解一下 js slice : 2.限制输入的数字最大值为10 3.限制输入的数字最小值为0 4.限制长度,大小

    2024年02月11日
    浏览(22)
  • input输入限制:自动补全两位小数、金额限制两位小数、只能输入正整数

    金额自动补全两位小数 限制只能输入正整数 金额限制两位小数 金额限制两位数,支持输入负数

    2024年04月17日
    浏览(14)
  • 腾达(Tenda)FH451路由器通过设置URL过滤限制网页访问

    适用路由器型号:F450/F451/F453/Ff455/F456/FH450/FH451 通过设置URL过滤来限制连接到该路由器下打开的网页,通过进入到路由器管理界面中(在地址栏中输入默认IP地址:192.168.0.1),在安全设置-URL过滤,中进行设置。 登陆管理界面 你需要登录到路由器管理界面来进行设置,此时,

    2024年02月06日
    浏览(17)
  • jQuery选择器(二)(基本过滤器,内容过滤器,可见过滤器)

    jQuery选择器(二)(基本过滤器,内容过滤器,可见过滤器)

    写在前面 jQuery是一个快速、简洁的 JavaScript 框架,是继Prototype之后又一个优秀的 JavaScript 代码库。jQuery的设计宗旨是“WriteLess,DoMore”,即倡导写更少的代码,做 更多的事情。jQuery封装了 JavaScript 常用的功能代码,提供一种简便的 JavaScript 设计模式,优化HTML文档操作、事件

    2024年02月02日
    浏览(12)
  • input 输入框限制只能输入两位有效小数

    input 输入框限制只能输入两位有效小数

    前端入门即教学,今天博主分享几个前端金额实用的小案例,复制拿过去就能用哦!    相信有很多前端小伙伴在工作中遇到过这样的需求,就是限制输入框内容只能输入两位小数吧,想了用正则但是又不知道怎么下手的同学,接下来博主分享一个小案例,下次遇到这个的时

    2024年02月01日
    浏览(13)
  • 防御保护--内容安全过滤

    防御保护--内容安全过滤

    目录 文件过滤 内容过滤技术 邮件过滤技术  应用行为控制技术 DNS过滤 URL过滤 防火墙 ---- 四层会话追踪技术 入侵防御 ---- 应用层深度检测技术 深度包检测 深度流检测 随着以上俩种的成熟与完善,提出了所谓的内容安全过滤 当然上网行为确实需要治理,需要内容安全过滤

    2024年02月21日
    浏览(4)
  • element ui限制输入框只能输入正整数

    element ui限制输入框只能输入正整数

    2024年02月11日
    浏览(11)
  • unity InputField输入框如何自定义输入类型,限制输入格式等

    Unity中的InputField输入框可以通过以下几种方式自定义输入类型,限制输入格式等: 通过设置InputField组件的content Type属性,可以指定输入框的类型。常见的类型有: Standard:默认类型,可以输入任何字符。 Integer Number:只能输入整数。 Decimal Number:只能输入浮点数。 Password:

    2024年02月08日
    浏览(9)
  • 【限制输入框值类型】自定义指令el-input输入类型限制,vue和html两个版本

    经常遇到输入框需要限制只能输入数字的, 因为用户很离谱,明显输入数字的地方他非要输入英文或者中文 但是用到UI框架或者自己写方法验证表单比较麻烦 为了一个输入框专门去弄一个验证很麻烦 所以这里就整合了两种自定义指令的方式,更加方便使用 vue版本和 html版本

    2024年02月05日
    浏览(13)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包