There is an example of url component on the official website, but it is relatively simple and not very useful, so let’s improve it.

The official website is very flexible, the three parts are shown separately. Well, let’s merge them together.

Defining common functions (improved)

The code that receives the value of the parent component’s V-Model property and commits the data is abstracted into a separate JS file so that various components can use it.

// controlManage.js
import { ref, watch } from 'vue'

/ * * * control of assignment and submit the unified management of function attributes: * * * * * props: component properties, obtain modelValue, and meta * * * the context: context access to emit, submit data back: * * * * * value: Value bound to component ** * mySubmit: Event submitted to parent component */
const controlManage = (props, context) = > {
  // The value used to bind the control.
  const value = ref(props.meta.defaultValue)

  // Get the properties set by the parent component
  const _value = props.modelValue

  // Set the control value. If there is a property value (modified state), the property value is set to the control value.
  if(! (_value ===' ' || _value === 0 || _value === null)) {
    value.value = _value
  }

  // Listen to the modelValue attribute and assign a value to value
  watch(() = > props.modelValue, (v1, v2) = > {
    // console.log('controlManage listen for property changes ', v1)
    value.value = v1
  })

  // Submit the event to the parent component
  const mySubmit = (val) = > {
    context.emit('update:modelValue', val)
    context.emit('input', val)
  }

  return {
    /** * The value used to bind the control. ** Add state to get the default value. ** To modify the state, you can set the modelValue value ** Listen to the modelValue attribute and assign a value to the value */
    value,
    /** submit an event to the parent component ** can be directly bound to the component's event, ** can also be nested. * /
    mySubmit
  }
}

export default controlManage

Copy the code

Comments and Hints

Writing comments this way will prompt you for easy viewing when calling.

process

  • Define value to bind control values.
  • Add status: set the default value to value;
  • Modify status: set v-Model to value;
  • Listen for the parent component’s V-Model and set it to value if there is a change.
  • Input event or other event, to the parent component.

Defines the management class of the URL

I like to write the related functions in a separate class, and try not to write setup if I can, so it looks cool.


/** * Handle url management class ** function: ** * Submit complete URL after concatenation ** * Provide binding control values, events ** * Automatically split properties when modified ** Parameter: ** * value: Control class value ** * mySubmit: control class mySubmit */
const urlManage = (value, mySubmit) = > {
  // Divide the URL into three parts
  const url = reactive({
    http: 'Https://'.com: '.com'.value: ' '
  })

  // Domain name suffix
  const comList = [
    { value: '.com' },
    { value: '.cn' },
    { value: '.net' },
    { value: '.com.cn' },
    { value: '.net.cn' },
    { value: '.org.cn' },
    { value: '.org' },
    { value: '.top' },
    { value: '.vip' },
    { value: 'China' },
    { value: 'companies' },
    { value: 'the company' },
    { value: 'network'}]// Split the attributes and assign a value to the URL
  watch(() = > value.value, (v1, v2) = > {
    const arrUrlAll = v1.toLowerCase().split(': / /')
    console.log('= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =')
    console.log(Parent component:, v1)
    // 判断 ://
    if (arrUrlAll.length === 1) { // Without http://, count directly to url.value
      url.value = arrUrlAll[0]}else if (arrUrlAll.length === 2) {
      url.http = arrUrlAll[0] + ': / /'
      // there is http://, split with
      const arrUrl = arrUrlAll[1].split('. ')
      const len = arrUrl.length
      let endPosition = 0
      switch (len) {
        case 1: // There is only one, which is directly counted as url.value
          url.value = arrUrl[0]
          break
        case 2: // There are two, one for url.value and one for com
          url.value = arrUrl[0]
          url.com = '. ' + arrUrl[1]
          break
        default: // There are more than two suffixes
          if (arrUrl[len - 1= = ='cn' && (arrUrl[len - 2= = ='com' || arrUrl[len - 2= = ='net' || arrUrl[len - 2= = ='org')) {
            endPosition = len - 2
            url.com = '. ' + arrUrl[endPosition] + '.cn'
          } else {
            endPosition = len - 1
            url.com = '. ' + arrUrl[endPosition]
          }
          url.value = arrUrl[0]
          for (let i = 1; i < endPosition; i++) {
            url.value += '. ' + arrUrl[i]
          }
      }
    }
  })

  // com query event
  const querySearch = (str, cb) = > {
    const results = str
      ? comList.filter((item) = >
        item.value.indexOf(str.toLowerCase()) === 0)
      : comList

    // Call callback to return the suggestion list
    cb(results)
  }

  // Three change events for the URL
  const urlSubmit = () = > {
    mySubmit(url.http + url.value + url.com)
  }

  return {
    url,
    querySearch,
    urlSubmit
  }
}
Copy the code
  • url

Because you’re splitting the URL in three, you define an object.

  • Suffix of domain name

Let’s see how many suffixes there are.

Is there a lot of domain names on the new web? And there are four special ones,.com. Cn,.net.cn,.gov.cn,.org.cn, and the others are all one dot, and these four are two dots. There are too many, here only the commonly used in the list, the rest can be filled in.

  • Add state

This is easy, just merge the three separate parts together and commit.

  • Modify the state of

This is a little tricky, because you need to separate the full URL and assign it separately. Did not think of a better method, first use this method to achieve, later think of a better optimization.

Defining the URL Component

Component is simple, reference two JS files, a concatenation is good.

<template>
  <el-input
    :placeholder="meta.placeholder"
    :maxlength="meta.maxlength"
    v-model="url.value"
    @input="urlSubmit"
  >
    <template #prepend><! -- the previous option -->
      <el-select style="width: 90px;"
        v-model="url.http"
        @change="urlSubmit"
        placeholder="Please select">
          <el-option label="Http://" value="Http://"></el-option>
          <el-option label="Https://" value="Https://"></el-option>
      </el-select>
    </template>
    <template #append><! -- domain name suffix -->
      <el-autocomplete style="width: 100px;"
        class="inline-input"
        v-model="url.com"
        :fetch-suggestions="querySearch"
        placeholder="Please enter content"
        @select="urlSubmit"
        @change="urlSubmit"
      ></el-autocomplete>
    </template>
  </el-input>
</template>

Copy the code
export default {
  name: 'nf-el-from-url'.props: {
    modelValue: String.meta: metaInput
  },
  emits: ['input'.'change'.'blur'.'focus'.'clear'],
  setup (props, context) {
    const { value, mySubmit } = controlManage(props, context)

    // const { url, querySearch, urlSubmit } = urlManage(value, mySubmit)

    return {
      ...urlManage(value, mySubmit)
      // querySearch, // com filter function
      // url, // url related values
      // urlSubmit // Triggers the event}}}Copy the code
  • The template

Based on the component modifications provided by Element-Plus.

  • return

In general, we refer to the function in setup, get the inner object, and then return it. If nothing else, you can use destruct to return the template directly.

Okay, that’s pretty much it. Simple test passed. Engineering is not convenient to do online demonstration, so do not demo first.

The effect

The domain name suffix is optional and can be changed. I just don’t know how to adjust the background color.

The source code

Github.com/naturefwvue…