vantソース分析--checkboxコンポーネント


この文章はuicompntがどのように作られたかを見てみます.vantの分割書き方はどのように優れていますか?私も最近は盲目的にvantのソースコードを考えています.
本稿の考えはここでジャンプできる文章から来ています.ここの考えを参考にしたものがたくさんあります.この文章の延長でもあります.
コンポーネントディレクトリ構造
src
└─ button
   ├─ demo             #     
   ├─ test             #     
   ├─ index.js         #     
   ├─ index.less       #     
   ├─ README.md        #     
   └─ README.zh-CN.md  #     
vantの車輪
vantのソースコードの中で、utilsは多くのツールと方法をパッケージ化しました.ts、tsx、js、vueなどの技術の倉庫に関連しました.
各コンポーネントは、オン時にはcreateNamespace関数を呼び出し、 (name)を受信し、createComponent, createBEM, createI18Nの3つの関数を返します.componentの例、cssヘルプクラスの関数、および多言語ツールです.
import {
      createBEM, BEM } from './bem';
import {
      createComponent } from './component';
import {
      createI18N, Translate } from './i18n';

type CreateNamespaceReturn = [
  ReturnType<typeof createComponent>,
  BEM,
  Translate
];

export function createNamespace(name: string): CreateNamespaceReturn {
     
  name = 'van-' + name;
  return [createComponent(name), createBEM(name), createI18N(name)];
}
1.createComponent
createComponentメソッドはパラメータnameによって、vueコンポーネントを作成します.
export function createComponent(name: string) {
     
 return function<Props = DefaultProps, Events = {
     }, Slots = {
     }>(
 	// sfc     createComponent             ,            
   sfc: VantComponentOptions | FunctionComponent
 ): TsxComponent<Props, Events, Slots> {
     
   if (isFunction(sfc)) {
       //             ,          
     sfc = transformFunctionComponent(sfc);
   }

   if (!sfc.functional) {
     
   	//mixins vue   ,                。
   	//           ,                     。
     sfc.mixins = sfc.mixins || [];
     //  push        scopedSlots mixin
     sfc.mixins.push(SlotsMixin);
   }

   sfc.name = name;
   // install    vue.compoent       
   sfc.install = install;

   return sfc as TsxComponent<Props, Events, Slots>;
 };
}
2.createBEM
createBEM関数は、nameパラメータを受信してBEM仕様に適合するクラスを生成する.
export function createBEM(name: string) {
     
 return function(el?: Mods, mods?: Mods): Mods {
     
   if (el && typeof el !== 'string') {
       //   el         string  
     mods = el;
     el = '';
   }
   el = join(name, el, ELEMENT); // join      checkbox__text   

   return mods ? [el, prefix(el, mods)] : el;  
 };
}
最後にBEM形式のクラス名を返します.
/**
 * bem helper
 * b() // 'button'
 * b('text') // 'button__text'
 * b({ disabled }) // 'button button--disabled'
 * b('text', { disabled }) // 'button__text button__text--disabled'
 * b(['disabled', 'primary']) // 'button button--disabled button--primary'
 */

3.createI 18 N
複数の言語処理
import {
      get, isFunction } from '..';
import {
      camelize } from '../format/string';
import locale from '../../locale';

export function createI18N(name: string) {
     
 const prefix = camelize(name) + '.';

 return function(path: string, ...args: any[]): string {
     
   const messages = locale.messages();
   const message = get(messages, prefix + path) || get(messages, path);

   return isFunction(message) ? message(...args) : message;
 };
}

export type Translate = ReturnType<typeof createI18N>;

vanコンポーネントcheckbox
vanコンポーネントcheckboxの具体的な配置
まず,createNamespace関数とmixinコンポーネントの多重化機能を導入した.そして、createNamespace関数を呼び出します.
import {
      createNamespace } from '../utils';
import {
      CheckboxMixin } from '../mixins/checkbox';

const [createComponent, bem] = createNamespace('checkbox');  //       createNamespace       
次はcheckboxのセットを導入する構成です.
//   createComponent              
export default createComponent({
     
  // mixins             
  //          props、computed、methods  rander  
  mixins: [
    CheckboxMixin({
     
      bem,
      role: 'checkbox',
      parent: 'vanCheckbox',
    }),
  ],
  // checked        checkbox v-model       
  computed: {
     
    checked: {
     
      get() {
     
        if (this.parent) {
     
          return this.parent.value.indexOf(this.name) !== -1;
        }
        return this.value;
      },

      set(val) {
     
        if (this.parent) {
     
          this.setParentValue(val);
        } else {
     
          this.$emit('input', val);
        }
      },
    },
  },
  //   value  ,      ,          
  watch: {
     
    value(val) {
     
      this.$emit('change', val);
    },
  },
  // methods         
  methods: {
     
    // @exposed-api
    // toggle         api
    toggle(checked = !this.checked) {
     
      // When toggle method is called multiple times at the same time,
      // only the last call is valid.
      // This is a hack for usage inside Cell.
      clearTimeout(this.toggleTask);
      this.toggleTask = setTimeout(() => {
     
        this.checked = checked;
      });
    },

    setParentValue(val) {
     
      const {
      parent } = this;
      const value = parent.value.slice();

      if (val) {
     
        if (parent.max && value.length >= parent.max) {
     
          return;
        }

        /* istanbul ignore else */
        if (value.indexOf(this.name) === -1) {
     
          value.push(this.name);
          parent.$emit('input', value);
        }
      } else {
     
        const index = value.indexOf(this.name);

        /* istanbul ignore else */
        if (index !== -1) {
     
          value.splice(index, 1);
          parent.$emit('input', value);
        }
      }
    },
  },
});