"Отзывы вознаграждаются" Начальник дал мне извращенную просьбу, а я стиснув зубы выполнил ее!

внешний интерфейс JavaScript Vue.js
"Отзывы вознаграждаются" Начальник дал мне извращенную просьбу, а я стиснув зубы выполнил ее!

Мало знаний, большой вызов! Эта статья участвует в "Необходимые знания для программистов«Творческая деятельность

Эта статья приняла участие"Проект "Звезда раскопок"", чтобы выиграть творческий подарочный пакет и бросить вызов творческим поощрительным деньгам.

предисловие

Вчера начальник неожиданно пришел ко мне на рабочее место и дал мне форму запроса:

В эту форму необходимо добавить поле "правило". Фон будет содержать содержимое по умолчанию. Вы помещаете это содержимое в поле ввода по умолчанию. Требование состоит в том, что пользователь может изменять только содержимое в скобках, а другое содержимое не может быть изменены.

Слышала голова, у меня до сих пор такой спрос!!Миллионы в душе проходят~а я не могу,начальник деньги дает,мне надо работать. Немного подумав, на самом деле функция этого требования все-таки должна быть реализована, и я начал это делать!

идеи

Как правило, поле ввода может свободно вводить текст, так как же ограничить поле ввода для ввода текста?Нам нужно ввести текст в поле ввода.el-inputнастраиватьvalueАтрибуты,valueпросто следуйте绑定的数据изменяется, в то время как связанные данные меняются в输入事件чтобы справиться с этим. Здесь нам нужно отказаться от предыдущего использованияv-modelспособ обновления значения изменения.Код выглядит следующим образом:

<el-input
  size="small"
  on-input={v => {
    item.__onChange && item.__onChange(v, form[item.__key], { form, key: item.__key })
  }}
  ref = { item.__key }
  props={{
    value: form[item.__key],
    placeholder: '输入内容信息',
    ...item
  }}
></el-input>

тогда нужно__onChangeКакие правила в нем прописаны, чтобы пользователи могли вводить контент только в скобках внутри контента, а другой контент оставался только читаемым? Поскольку другой контент只读, в скобках указано可写Содержимое круглых скобок, далее приходит идея, мы можем удалить измененное содержимое в круглых скобках, а затем при вводе давайте сравним, все ли содержимое после удаления круглых скобок такое же, как и предыдущее содержимое Удалим круглые скобки Содержимое равны, если они равны, это доказывает, что содержимое, введенное пользователем, вводится в круглых скобках, и данные обновляются до данных, введенных пользователем. В противном случае он не будет обновляться.

разработка правил

Теперь, когда у нас есть идея, давайте начнем!

  this.formArr =  new createForm()
  .createInput({
    __key: 'rule',
    label: '规则',
    type: 'textarea',
    __notAutoInput: true,
    __defaultVal: '今日信息: 娱乐新闻(XX)条, 体育新闻(XX)条',
    __onChange:  (inputVal, val, { form, key }) => {
      // inputVal 用户输入的内容
      // val 目前页面显示的内容(输入之前的内容)
      let reg = /\([\w\W]*?\)|([\w\W]*?)/g // 兼容中英文两种括号
      let input = inputVal.replace(reg, '') // 去掉现在在输入的内容括号里边的空格
      let value = val && val.replace(reg, '') // 去掉括号里边原来的内容的空格
      if (input === value) { // 比对去掉空格内容后,是否一致,如果是一致的话,则说明没有修改空格以外的内容,则让用户修改
        form[key] = inputVal // 数据更新成用户输入的内容
      }
    }
  }).form

GIF.gifЧто ж, наша функция в основном завершена. Ха-ха. Я пошел сдавать функцию и показал ее начальнику, начальник попробовал и молча сказал:"你这基本功能是实现了,但是总体体验不是太好呀,我在小括号以外的地方输入的时候,老会跳到文字的最后面去了,你再去把这里优化优化吧!" , я... (тысячу раз опущено здесь), после того, как я выплеснул свои эмоции, моя жизнь все равно должна пойти ко дну. Итак, давайте искать информацию, чтобы увидеть, есть ли решение.

Введение в API оптимизации

Наконец, с помощью Google я нашел API, который может достичь этой оптимизации.

setSelectionRange

HTMLInputElement.setSelectionRangeспособ установки<input> или <textarea>Начальная и конечная позиция выделенного в данный момент текста в элементе

В сочетании с соответствующими API они могут реализовать переход фокуса к местоположению указанного контента. После того, как у нас есть пригодный для использования API, давайте напишем демо, чтобы попробовать его:

<body>
    <textarea id="txtUserID" oninput="inputHandle()"></textarea>
    <script>
        var textbox = document.getElementById("txtUserID")
        textbox.value = '123456789'
        function setFocus(textbox, index) {
          if (textbox.setSelectionRange) {
            textbox.focus();
            textbox.setSelectionRange(index, index + 3);
          }
        }
        function inputHandle(v) {
          setFocus(textbox, 2)
        }
    </script>
</body>

F5A00B06-BF10-4413-A3CB-9ECA747C87E2.pngиспользоватьsetSelectionRangeМетод передает два параметра.Если начальный параметр и последний параметр несовместимы, могут быть реализованы произвольные данные.选中, если начальный параметр и последний параметр совпадают, вы можете установить фокус в любую позицию.

Оптимизация разработки

В демонстрации мы знаем, что для установки фокуса нам нужно получить объект dom поля ввода и позицию пользовательского ввода, так как же получить позицию пользовательского ввода? Мы можем выполнять содержимое, отображаемое на странице, и содержимое, которое пользователь вводит посимвольно.对比,до发现两个字符串对比出不一样символ, выйти из цикла и вернуть текущий индекс строки. это索引的位置减一Это позиция, которую ввел пользователь, далее мы напишем функцию сравнения строк

// 找到索引
findIndex (newVal, oldVal) {
  let newValArr = newVal.split('')
  let oldValArr = oldVal.split('')
  for (let i = 1; i <= newVal.length; i++) {
    let newItem = newValArr.slice(0, i)
    let oldItem = oldValArr.slice(0, i)
    if (JSON.stringify(newItem) !== JSON.stringify(oldItem)) {
      return i
    }
  }
  return newVal.length
}

Затем следует воспользоваться методом установки фокуса, который был написан в демо ранее.

// 设置焦点
setFocus (textbox, index) {
  if (textbox.createTextRange) {
    var r = textbox.createTextRange();
    r.collapse(true);
    r.moveStart('character', index);
    r.select()
  } else if (textbox.setSelectionRange) {
    textbox.focus();
    textbox.setSelectionRange(index, index);
  }
}

Наконец, мы добавляем к ранее написанной форме, что если пользователь не вводит в круглых скобках,比对字符串,а также设置焦点основная логика.

this.formArr =  new createForm()
.createInput({
  __key: 'rule',
  label: '规则',
  type: 'textarea',
  __notAutoInput: true,
  __defaultVal: '今日信息: 娱乐新闻(XX)条, 体育新闻(XX)条',
  __onChange:  (inputVal, val, { form, key }) => {
    let reg = /\([\w\W]*?\)|([\w\W]*?)/g // 兼容中英文两种括号
    let input = inputVal.replace(reg, '') // 去掉现在在输入的内容括号里边的空格
    let value = val && val.replace(reg, '') // 去掉括号里边原来的内容的空格
    if (input === value) { // 比对去掉空格内容后,是否一致,如果是一致的话,则说明没有修改空格以外的内容,则让用户修改
      form[key] = inputVal
    } else {
      // 如果用户没有在小括号内输入的时候,比对字符串,并设置焦点的主逻辑
      let index = self.findIndex(inputVal, val)
      let dom = self.$refs.myForm.$el.querySelector(`textarea[aria-label=规则]`)
      if (dom && (index || index === 0)) {
        // 由于
        setTimeout(() => {
          self.setFocus(dom, index - 1)
        }, 10)
      }
    }
  }
}).form

Конечный эффект:

GIF.gif

напиши в конце

Хорошо, тогда это небольшая проблема, с которой я столкнулся в реальной работе. Хотя я чувствую, что какое-то время меня усложняли, и хотя поиск информации занял некоторое время, в конце концов, результат все равно приятный. Написав, босс доволен, и я тоже чувствую, что чему-то научился. Еще вполне доволен. Ха-ха!