vant 소스 코드 분석 -- checkbox 구성 요소

이 글 은 ui copent 가 어떻게 만 들 어 졌 는 지, vant 의 분할 쓰기 가 어떻게 우수한 지 보 는 것 이다.본인 도 요즘 vant 소스 만 생각 하고 있 습 니 다.
본문의 사상 은 이곳 에서 뛰 어 넘 을 수 있 는 문장 에서 기원 되 었 다.이곳 의 생각 을 참고 한 것 도 이 문장의 연장 이 죠.
구성 요소 디 렉 터 리 구조
src
└─ button
   ├─ demo             #     
   ├─ test             #     
   ├─ index.js         #     
   ├─ index.less       #     
   ├─ README.md        #     
   └─ README.zh-CN.md  #     

vant 바퀴
vant 소스 코드 에서 utils 에는 많은 도구 와 방법 이 봉인 되 어 있다.ts, tsx, js, vue 등 기술 창고 와 관련 되 었 습 니 다.
모든 구성 요 소 는 열 리 면 4. 567914. 함 수 를 호출 합 니 다. 4. 567914 를 받 고 4. 567914. 세 개의 함 수 를 되 돌려 줍 니 다.즉, comonent 인 스 턴 스, 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 규범 에 맞 는 class
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 형식 과 유사 한 class 클래스 이름 을 되 돌려 줍 니 다.
/**
 * 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. createI18N
다 국어 처리
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 구성 요소 확인 란
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);
        }
      }
    },
  },
});

좋은 웹페이지 즐겨찾기