The preface

This chapter will share the Radio article of the Element-UI source code. The rhythm of the article is to share the normal Element directory structure, starting with the components in the Form. So the first one is Radio

Component process

  1. The process of component code going from 0 to 1
  2. The index component introduces the install method and throws it
  3. Main.js is introduced collectively
  4. Use the vue.use method to register
  5. Used in the last page

The last? Is the location of the source: packages/radio/SRC/radio. The vue.

In the radio folder there is an index.js that registers the component and throws it. SRC is used to put the component code, but the radio component code is much more than the Button. Radio.vue, radio-button.vue, radio-group.vue, if you can see the names of these files, you can guess a lot.

Structure analysis

We start with three aspects of each VUE file: DOM structure, data attributes, events,

Ii. Element does three kinds of work for radio, namely, basic usage, single box group and button style, which can be corresponding one by one according to the above VUE file.

Radio Basic

DOM structure

    <label>
        <span>
            <span></span>
            <input/>
        </span>
        <span>
            <slot></slot>
            <template v-if=! "" $slots.default">{{ label }}</template>
        </span>
    </label>
    
    
    <label
        class="el-radio"
        :class="[ border && radioSize ? 'el-radio--' + radioSize : '', { 'is-disabled': isDisabled }, { 'is-focus': focus }, { 'is-bordered': border }, { 'is-checked': model === label }, ]"
        role="radio"
        :aria-checked="model === label"
        :aria-disabled="isDisabled"
        :tabindex="tabIndex"
        @keydown.space.stop.prevent="model = isDisabled ? model : label"
    >
        <span
            class="el-radio__input"
            :class="{ 'is-disabled': isDisabled, 'is-checked': model === label, }"
        >
            <span class="el-radio__inner"></span>
            <input
                ref="radio"
                class="el-radio__original"
                :value="label"
                type="radio"
                aria-hidden="true"
                v-model="model"
                @focus="focus = true"
                @blur="focus = false"
                @change="handleChange"
                :name="name"
                :disabled="isDisabled"
                tabindex="1"
            />
        </span>
        <span class="el-radio__label" @keydown.stop>
            <slot></slot>
            <template v-if=! "" $slots.default">{{ label }}</template>
        </span>
    </label>
Copy the code

And the question is, right? Why Radio is not only an input label, why does it need to be wrapped with label? Label label, as its name implies, is the label of the presentation class, but it still has another function!

In a separate input box, the user can only focus the input box by clicking on it when he wants to enter something.

< inpust id=”account” name=”account” >

If you surround the input with a label, the focus is automatically on the input box when the text displayed by the label is clicked. And the way to do that is for label = “Id of the input box”

< /label > < input ID =”account” name=”account”/ >

Two operations are triggered when the label is clicked, one for the label and one for the input to automatically get focus.

label
  • Class =”el-radio” : radio mode

  • Class: style specific

    –border && radioSize ? ‘el-radio–‘ + radioSize: ‘: radio size Size of the radio, valid only if border is true

    — IS-disabled ‘: isDisabled: disabled

    — IS-focus ‘: focus: selected style

    — IS-bordered ‘: border: border

    — IS-checked ‘: model === label: Indicates whether the button is checked

  • Role =”radio” : Accessible web application attribute

    –:aria-checked=”model === label”

    –:aria-disabled=”isDisabled”

    Web accessibility applications. This is for visually impaired, deaf, mobility impaired people and those who pretend to be disabled. Especially for the blind, the eyes can not see, it needs to use auxiliary devices to browse the web, such as screen readers, screen readers can read aloud or output braille. ARIA is a technology that allows screen readers to accurately identify the content, changes, and states of a web page, making it accessible to the blind!Copy the code

    Wai-aria barrier-free Web application properties fully display address

  • : tabIndex =”tabIndex” : the TAB key is used to obtain the focus. -1 indicates that the focus is unavailable, and 0 indicates that the focus is optional

  • @keydown.space.stop.prevent=”model = isDisabled ? Model: the label “:

    Keydown. space press space,

    Stop bubbling,

    Prevent Prevents default behavior

    When TAB selects the current radio and hits the space bar (space bar) on the keyboard, the native event is prevented

label > span
  • Class =”el-radio__input” : radio style

  • Class: — IS-disabled: isDisabled. — IS-checked ‘: model === label: indicates whether to select

label > input
  • Ref =”radio” : register ref

  • Opacity: 0 class=”el-radio__original” : 0

  • :value=”label” :value of the Radio

  • Type =”radio” : input type

  • Aria-hidden =”true” : 1. Make this element hidden from the browser 2. To prevent screen – reading devices from capturing unintentional and potentially confusing output

  • V-model =”model” : binding value

  • @change=”handleChange” : native change event

  • :name=”name” : Multiple same name attributes in a group

  • : disabled = “isDisabled” : disabled

  • Tabindex =”-1″ : Disables TAB selection

Note: If -1 is used, the onfocus and onblur events are still started

1. Native tag Radio is different from browser to browser, so write your own tag instead of 2. Instead of dispaly: None or Visibility: Hidden, element uses a native radio to get focus and trigger the change event, so element uses absolute positioning to be out of the document stream and to set transparency to 0Copy the code

Data attributes

    name: "ElRadio".mixins: [Emitter],
    inject: { // It is related to the Form Form
        elForm: {
            default: "",},elFormItem: {
            default: "",}},componentName: "ElRadio".props: { // Attribute passing is not explained here
        value: {},
        label: {},
        disabled: Boolean.name: String.border: Boolean.size: String,},data() {
        return {
            focus: false}; },computed: {
        isGroup() {
            let parent = this.$parent; // 
            while (parent) {
            // Loop up to find its parent, return true if it can find the parent component whose name is ElRadioGroup, false otherwise
                if(parent.$options.componentName ! = ="ElRadioGroup") {
                    parent = parent.$parent;
                } else {
                   // If radio group, save a reference to the group component
                    this._radioGroup = parent;
                    return true; }}return false;
        },
        model: {
            get() {
                Radio-group = radio-group; radio-group = radio-group
                return this.isGroup ? this._radioGroup.value : this.value;
            },
            set(val) {
                if (this.isGroup) {
                    this.dispatch("ElRadioGroup"."input", [val]);
                } else {
                    this.$emit("input", val);
                }
                this.$refs.radio && (this.$refs.radio.checked = this.model === this.label); }},_elFormItemSize() {
            return (this.elFormItem || {}).elFormItemSize;
        },
        radioSize() {
            const temRadioSize = this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
            return this.isGroup ? this._radioGroup.radioGroupSize || temRadioSize : temRadioSize;
        },
        isDisabled() {
            return this.isGroup
                ? this._radioGroup.disabled || this.disabled || (this.elForm || {}).disabled
                : this.disabled || (this.elForm || {}).disabled;
        },
        tabIndex() {
             // If the disabled state or radio button is in the menu group component and is not selected, -1 is returned;
            return this.isDisabled || (this.isGroup && this.model ! = =this.label) ? -1 : 0; }}Copy the code

computed

  • IsGroup () : checks whether a radio group exists

  • model :

  • _elFormItemSize: Gets the size of fromItem

  • RadioSize: Controls the size of the radio

  • IsDisabled: indicates whether the component isDisabled

  • TabIndex: Set tab-index of a component

The event

     handleChange() {
        this.$nextTick(() = > {
            // Triggers the change event on the instance
            this.$emit("change".this.model);
            // Group, triggers the handleChange event under the parent component named ElRadioGroup, also taking the currently selected value as an argument
            this.isGroup && this.dispatch("ElRadioGroup"."handleChange".this.model);
        });
    },
Copy the code

Since there are a lot of Radio, I will write it in two parts. The next one is radio-group and radio-button.

At the end of the

Living beings, who does not love life? Love of life, and love group ---- no prize contestCopy the code