vue-develop-template icon indicating copy to clipboard operation
vue-develop-template copied to clipboard

有ts 版本的吗

Open nailfar opened this issue 6 years ago • 8 comments

nailfar avatar Jun 25 '18 06:06 nailfar

@nailfar 还没呢 着急的话可以先自己重写下 应该花不了多久

PerseveranceZ avatar Jun 26 '18 01:06 PerseveranceZ

主要是ts 下有些问题 无法解决 。没有找到一些合适的方案; 比如在vue ts中使用 mixins 怎么做类型检测。 通过 @Component() 在 组件中使用时没有类型检测;

import Vue from "vue";
import { IResponseList } from "@/api/model/response";
/*与后端约定的数据接口*/
export interface IPage<M> {
  list: M[];
  size: number;
  total: number;
}
export default abstract class Pagination< M, T extends IResponseList<M> = IResponseList<M>> extends Vue {
  public total: number = 0;
  public page: number = 1;
  public size: number = 20;

  get pageParam(): { size: number; page: number } {
    return {
      page: this.page - 1,
      size: this.size,
    };
  }

  public onSizeChange(size: number) {
    console.info(`当前每页${size}条`);
    this.size = size;
    this.page = 1;
    this.getPage();
  }

  public onPageChange(page: number) {
    console.info(`当前第${page}页`);
    this.page = page;
    this.getPage();
  }

  public firstPage() {
    this.page = 1;
    this.refreshPage();
  }

  public goPage(page: number) {
    this.page = page;
  }

  public refreshPage() {
    this.getPage();
  }

  abstract handlePage(pageParam: { page: number; size: number }): Promise<T>;

  private getPage() {
    this.handlePage(this.pageParam).then((resp) => {
      this.total = resp.total;
      this.size = resp.size;
    });
  }
}
@Component({
  mixins: [Pagination],
})
export default class Coupon extends Vue {
 couponList:Coupon[]=[];
/*覆盖 pagination 抽象方法 获取数据*/
 handlePage(param):Promise<IPage<Coupon>>{
   return  API.getCoupons(param).then(resp=>{ this.couponList=resp.list; return resp})
 }
  render(h){
    return <div>
<table data={this.couponList}></table>
<el-pager page= {this.page} size={this.size} 
onPageChange={this.onPageChange /*这里的page size onPageChange是没有类型检测的。因为在minins里  ts编译器无法探测到这个属性方法*/ } ></el-pager></div>
  }
  mounted() {
     
  }
}

官网给出的方案是

declare module 'vue/types/vue' {
  interface Vue {
    page: any,
    size: any,
    ...
  }
}

这样解决只能暂时解决,当minxins 和模块数量增加以后 挂载在vue 的属性声明越来越多就难免会冲突。这种解决方式不是很完美,对小型项目还适用。 也尝试过直接 继承 Pagination 类 但是ts只能单继承,多个minixn 的情况就无法适用。若果使用implements 可以多实现 但是就无法隐藏一些实现细节,显然这不是我想要的。大佬可有解决方案

nailfar avatar Jun 26 '18 09:06 nailfar

@nailfar 抱歉现在才来回你,mixins 就是有这样的问题,如果要这么使用,暂时也没什么好的解决方式

不过抽离很多不同功能的 mixins,或者大量 mixins 我觉得可能有些不太妥:

  1. 就如你说的,当minxins 和模块数量增加以后 挂载在vue 的属性声明越来越多就难免会冲突,每个组件的“性能”自然也会不好,即便是你做命名空间,但这又何尝不是增大了工作量,降低了代码可读性。
  2. 一个业务中可能就用到就 5 个 mixins 的 5个方法,肯定会有冗余,而且会随着业务增长而增长。
  3. 后期维护起来是比较困难的,就怕有交叉。

是否可以尝试换种思路,不要用 mixins。

PerseveranceZ avatar Jun 27 '18 02:06 PerseveranceZ

@PerseveranceZ 没事,我也是闲暇才回复。

可能之前用 es6 编码时 滥用了很多mixins ,觉得它确实能复用不少代码,还能组合不同功能到一个新组件上。同时也感受到它的弊端: 我在某个方法中使用了 一个 mixins中的方法 ,别人完全不知道这个方法哪里来的,在阅读代码的时候确实挺痛苦的。现在转了ts 以后 希望类型推导能完美解决 这个痛点。

虽然ts官网也给出了一些minixs的解决方案 ,但是不是很友好 ,过程繁琐,目前正在使用此方案。

// Mixin
class Disposable {
  isDisposed: boolean;
  dispose() {
      this.isDisposed = true;
  }

}

// Mixin
class Activatable {
  isActive: boolean;
  activate() {
      this.isActive = true;
  }
  deactivate() {
      this.isActive = false;
  }
}
// 使用的vscode 自动implements 代码量不是很多  但是繁琐
class SmartObject implements Disposable, Activatable extends Vue {
  isDisposed: boolean;
  isActive: boolean;
  dispose(): void {
    throw new Error("Method not implemented.");
  }
  activate(): void {
    throw new Error("Method not implemented.");
  }
  deactivate(): void {
    throw new Error("Method not implemented.");
  }
  interact() {
    this.activate();
  }
}
applyMixins(SmartObject, [Disposable, Activatable])
function applyMixins(derivedCtor: any, baseCtors: any[]) {
  baseCtors.forEach(baseCtor => {
      Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
          derivedCtor.prototype[name] = baseCtor.prototype[name];
      })
  });
}

class myComponent extend SmartObject {
  this.dispose()  
}

就目前来看 class A extends MixinsA 能等同 vue.extends ,而且完美契合。唯有extends不能多继承。

nailfar avatar Jun 27 '18 07:06 nailfar

@nailfar 这方案非常好啊~,你可以 fork 一份项目 pr 一下你这套规范呢

PerseveranceZ avatar Jun 28 '18 10:06 PerseveranceZ

等项目框架稳定了我再pr 吧 最近比较忙 今天发现个更简单的方法 @Component({ mixins:[Disposable , Activatable ] }) class SmartObject extends Vue< Disposable & Activatable > { constructor(){ // } }

nailfar avatar Jul 09 '18 03:07 nailfar

@nailfar 最近在写 ts 版本的了,这边使用 vue-class-component 是可以进行类型检测的

<script lang="ts">
import { Provide, Watch, Vue } from 'vue-property-decorator'
import Component, { mixins } from 'vue-class-component'
import { test1Mixin, test2Mixin } from '@/mixins/mix-test.ts'
import HelloWorld from '@/components/HelloWorld.vue' // @ is an alias to /src

interface Person {
    name: string
    age: number
}

@Component({components: { HelloWorld }})
export default class Home extends mixins(test1Mixin, test2Mixin) {
  @Provide() test: string = 'hahhahaha'
  @Provide() person: Person = {
    name: 'ddddddddd',
    age: 123
  }
  @Provide() timeout: number = 3000
  @Provide() hellowMsg: string = 'hahah'
  @Provide() inputValue: string = '123'

  @Watch('inputValue')
  onInputValueChanged (val: string, oldVal: string) {
    console.log(val)
  }

  changeTest () : void {
    setTimeout(() => {
      this.test = 'xxx'
    }, this.timeout)
  }

  mounted () {
    // this.mixin2Value = 123
    this.changeTest()
  }
}
</script>

PerseveranceZ avatar Aug 21 '18 03:08 PerseveranceZ

@PerseveranceZ 最近项目赶进度暂时没时间写 vue-class-component 出的 mixins 挺好用。我已经在项目里使用了。 vue-cli 3.0 版本对ts 也支持的。减少了很多ts 方面的配置。tsx 还是需要自己配置。

nailfar avatar Aug 22 '18 03:08 nailfar