其他说明
- shims-vue.d.ts 主要用于让 ts 识别 .vue 文件
- shims-tsx.d.ts 在 ts 中可以使用 jsx 语法
declare module 'vue/types/vue' {
type Abc = () => void;
interface Vue {
$abc: Abc;
}
}
- global.d.ts 新建来定义一些不识别的模块。如:
.scss|css|png等
- 如果使用了
@vue/cli-plugin-babel就不用再安装jsx相关依赖了
- 它内部使用了
babel-preset-app库,而这个库已经依赖了jsx相关的包
vue-property-decorator/vue-class-component
- 官网文档:链接 链接
@Component({})可配置所有的vue.options内容
- 使用
tsx语法不用手动配置components内容,直接引入即可
import { Vue, Component, Prop, Emit, Ref, Provide, Inject, Watch } from 'vue-property-decorator';
import { Button } from 'vant';
import styles from './TodoItem.module.scss';
@Component
export class TodoItem extends Vue {
@Prop()
index!: number;
@Prop({ type: Object, default: () => ({}) })
data!: ITodoItem;
count: number = 0;
@Watch('person', { immediate: true, deep: true })
onPersonChanged(val: Person, oldVal: Person) {}
@Ref()
readonly refCmp!: RefCmp;
@Provide()
delItem(id: number) {}
@Inject()
readonly delItem!: (id: number) => void;
private add(): void {
this.count += 1;
}
public get total(): number {
return this.count + 1;
}
public set total(v: number) {
this.count = v;
}
private render() {
{}
return <RefCmp ref="refCmp"></RefCmp>;
}
}
vuex-module-decorators/vuex-class
- 创建store时 vuex-module-decorators(dev-save) 链接
- 使用时 vuex-class 链接
import { Module, Mutation, VuexModule, getModule } from 'vuex-module-decorators';
export interface ITodoState {
list: ITodoItem[];
listState: Mode;
}
@Module({ dynamic: true, name: 'todo', store })
export class Todo extends VuexModule implements ITodoState {
list: ITodoItem[] = [];
public get listByState(): ITodoItem[] {
return this.list;
}
@Mutation
add(payload: ITodoItem): void {
}
@Action
async fetchNewWheels(wheelStore: string) {
const wheels = await get(wheelStore)
this.context.commit('addWheel', wheels)
}
}
export const TodoModule = getModule(Todo)
export default class TodoList extends Vue {
@Getter('listByState', { namespace: 'todo' })
readonly todoList!: ITodoItem[];
@Mutation('changeListState', { namespace: 'todo' })
private mutationsChangeListState!: (state: null | 0 | 1) => void;
}
jsx 语法
- JSX 的本质就是 JavaScript,所以它具有 JavaScript 的完全编程能力
- 在jsx语法内一切皆是
prop统一了使用规则。编译器最终会把props转为不同的内容
- 基础用法:不在使用
v-bind|v-on语法,变量、事件等绑定使用xXx={this.xxx}
- 内置指令: 只支持
v-show|v-model
v-if|v-for使用JS逻辑去实现
v-html使用<div domPropsInnerHTML={xxx}>实现
{}
<input type="text" vModel_trim_number={this.value} />
{}
<input type="text" onInput={this.onManualInput} />
private onManualInput(e: InputEvent) {
const value = (e.target as HTMLInputElement).value;
this.inputValue = value;
}
{}
<p vShow={this.isShow}>is show</p>
{}
const todoItem = this.list.map((item, index) => {
return <TodoItem key={item.id} index={index} data={item} />;
});
<div class="todo-list__scroll">{todoItem}</div>
- 事件绑定:使用
onEventName={this.methodName}方式,自己去处理修饰符的功能(建议使用)
- 也可使用
vOn:eventName_modifier_modifier={this.methodName}方式,可配置vue默认的修饰符
- 原生事件
nativeOnXXX={this.xxx}绑定在组件的根标签上
{}
<a href="" onClick={this.clickADom}></a>
private clickADom(e: PointerEvent) {
e.preventDefault();
e.stopPropagation();
}
{}
<div onClick={(e: PointerEvent) => this.clickTarget(e, 'abc')}></div>
private clickTarget(e: PointerEvent, str: string) {}
{}
<div class="c2" onClick={this.onClickBind.bind(this, 'abc', 333)}></div>
private onClickBind(str: string, num: number, e: PointerEvent) {}
{}
<ChildCmp onCallback={this.callback} />
- 自定义 directive
- 修饰符也是通过
_连接传递vPermission_a_b
export const permission: DirectiveOptions = {
inserted(el, binding) {
console.log(el, binding);
}
};
@Component({
directives: {
permission
}
})
export class AllProps extends Vue {
private render() {
return (
<ChildCmp vPermission_a_b="xxx" />
)
}
}
- $arrts|$listeners 绑定
- 一切皆
props:在JSX内标签上所有 onXxx 都会进入 listeners内,其他非语法内置props或组件内未设置‘@Prop‘接受的都会进入attrs
{}
const cusAttrs = { staticParam: 'abc', reactiveParam: this.isShow };
<CusCmp {...{ attrs: cusAttrs }} />
{}
const cusAttrs2 = { ref: 'input', class: ['a', 'b'], attrs: {/..传递的属性../}, on: {/..传递的事件../} };
<CusCmp {...cusAttrs2} />
<p vShow={this.$attrs.isShow}>c 1</p>
<p onClick={this.$listeners.testFn}>count++</p>
const cusScopedSlots = {
footer: (props) => <p>this is scoped slot {props.value}</p>;
};
{}
<SlotCmp scopedSlots={cusScopedSlots}>
{}
<p>this is default slot</p>
{}
<div slot="header">this is named slot</div>
</SlotCmp>
{}
<div class="slot-cmp-inner">
<p>slot cmp</p>
{}
<div class="slot-default">{this.$slots.default}</div>
{}
<div class="slot-named">{this.$slots.slotName ? this.$slots.slotName : null}</div>
{}
<div class="slots-scoped">{this.$scopedSlots.slotName ? this.$scopedSlots.slotName(this.itemData) : null}</div>
</div>
cssModule
- 编译的结果是把
className按对象形式传递出来{ todo-item: "TodoItem-module_todo-item_H_L6b" },本质内容是包含嵌套关系的
- 可通过在vue.config.js内配置css选项修改
localIdentName: '[path][name]__[local]--[hash:base64:5]'
:local/:global为作用域选择器
:global .className就不在本模块内出现,变为全局样式(既命名规则不在按照localIdentName)
- 注意: 不支持vue的深度样式选择器,因为不在.vue内编写

部分装饰器实现逻辑
- vuex-class 的
@State装饰器逻辑
- 主要逻辑是把
@State('list', { namespace: 'todo' }) readonly todoList!
- 转为为
computed: { todoList: mapState({ todoList: 'list' })['todoList'] }
mapState({ todoList: 'list' })返回的是个对象
export var State = createBindingHelper('computed', mapState);
function createBindingHelper(bindTo, mapFn) {
function makeDecorator(map, namespace) {
return createDecorator(function (componentOptions, key) {
if (!componentOptions[bindTo]) {
componentOptions[bindTo] = {};
}
var mapObject = (_a = {}, _a[key] = map, _a);
componentOptions[bindTo][key] = namespace !== undefined
? mapFn(namespace, mapObject)[key]
: mapFn(mapObject)[key];
var _a;
});
}
function helper(a, b) {
if (typeof b === 'string') {
var key = b;
var proto = a;
return makeDecorator(key, undefined)(proto, key);
}
var namespace = extractNamespace(b);
var type = a;
return makeDecorator(type, namespace);
}
return helper;
}
- vuex-module-decorators 的
@Mutation逻辑
- 把 mutations 关联到
module.mutations[key]=Fn上
export function Mutation<T extends Object, R>(
target: T,
key: string | symbol,
descriptor: TypedPropertyDescriptor<(...args: any[]) => R>
) {
const module = target.constructor as Mod<T, any>
if (!module.hasOwnProperty('mutations')) {
module.mutations = Object.assign({}, module.mutations)
}
const mutationFunction: Function = descriptor.value!
const mutation: Mut<typeof target> = function (state: typeof target, payload: Payload) {
mutationFunction.call(state, payload)
}
module.mutations![key as string] = mutation
}