vantソース分析--checkboxコンポーネント
27159 ワード
この文章はuicompntがどのように作られたかを見てみます.vantの分割書き方はどのように優れていますか?私も最近は盲目的にvantのソースコードを考えています.
本稿の考えはここでジャンプできる文章から来ています.ここの考えを参考にしたものがたくさんあります.この文章の延長でもあります.
コンポーネントディレクトリ構造
vantのソースコードの中で、utilsは多くのツールと方法をパッケージ化しました.ts、tsx、js、vueなどの技術の倉庫に関連しました.
各コンポーネントは、オン時には
createComponentメソッドはパラメータnameによって、vueコンポーネントを作成します.
createBEM関数は、nameパラメータを受信してBEM仕様に適合するクラスを生成する.
複数の言語処理
vanコンポーネントcheckboxの具体的な配置
まず,createNamespace関数とmixinコンポーネントの多重化機能を導入した.そして、createNamespace関数を呼び出します.
本稿の考えはここでジャンプできる文章から来ています.ここの考えを参考にしたものがたくさんあります.この文章の延長でもあります.
コンポーネントディレクトリ構造
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.createComponentcreateComponentメソッドはパラメータ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.createBEMcreateBEM関数は、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コンポーネントcheckboxvanコンポーネント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);
}
}
},
},
});