Обновление 2020 г.
Недавно я перечитал эту статью и обнаружил, что эта статья не отмеченаts
Предварительный выпуск и предварительный выпуск, поэтому был добавлен предварительный выпуск, и среда для написания этой статьиVue 2.5.*
, это может быть неподходящим для текущей среды, некоторые плагины или некоторые методы реализации могут быть изменены, илиVue
У официалов разные способы реализации, поэтому эта статья до сих пор используется как справочная, ведь эта статья18
Год написан.
Недавно я попробовал TypeScript и попытался изменить проект Vue на TypeScript, и это хорошо. В настоящее время сотрудничество между Vue и TypeScript не идеально. Сотрудничество между Vuex и TypeScript очень плохое. Вы должны быть осторожны при попытке. Если вы хотите испытать это, настоятельно рекомендуется использовать vue-cli 3 для напрямую сгенерируйте каталог проекта, что потребует гораздо меньше настроек, например, с помощью tsconfig или чего-то еще, просто выберите TypeScript при использовании vue-cli.
Если вы хотите испытать конфигурацию с 0, обратитесь к этому документу.TypeScript-Vue-Starter
Начальная конфигурация здесь не упоминается, потому что Vue-CLI уже настраивается по умолчанию. В корневом каталоге есть файл TSConfig.json, а под папкой SRC есть SHIMS-TSX.D.TS, Shims-Vue .D .S файлы
Файл shims-vue.d.ts в основном используется для TypeScript для распознавания файлов .vue. По умолчанию Ts не поддерживает импорт файлов vue. Этот файл указывает ts импортировать файлы .vue, нажавVueConstructor<Vue>
обработки, поэтому файл импорта vue должен написать суффикс .vue, но это также приведет к тому, что даже если путь к импортированному файлу .vue, который вы пишете, неверен, статическое обнаружение не обнаружит ошибку, если вы поместите мышь выше вы увидите, что неправильный путь указывает на этот файл, потому что вы определили этот модуль, что все импорты с суффиксом .vue будут указывать на этот файл, но если ваш путь правильный, ts может прочитать правильный модуль.
Может быть, бесполезно так много говорить, просто посмотрите на следующие две картинки, чтобы понять
файл shims-tsx.d.ts, этот файл в основном для того, чтобы вы использовали синтаксис jsx в ts, если вы не используете синтаксис jsx, вы можете его игнорировать, но настоятельно рекомендуется использовать синтаксис jsx, в конце концов, шаблоны не может получить подсказки статического типа Да, конечно, если ваша область высокая, используйте функцию рендеринга vue напрямую. Если вы хотите использовать синтаксис jsx, сотрудничайте с babel-plugin-jsx-v-model, этот плагин имеет лучший опыт.Этот плагин реализует v-модель в синтаксисе jsx.
Это хорошо, чтобы понять вышеперечисленные вещи, в основном нет необходимости менять
Поддержка редактора
Рекомендуются плагины Visual Studio Code и Vetur, а если вы используете IDE, рекомендуется WebStorm.
При написании Vue с помощью TypeScript есть два основных способа:Vue.extend()
а такжеvue-class-component
-
Vue.extend()
: Используя базовый конструктор Vue, создайте «подкласс». Этот метод наиболее близок к однофайловому методу написания компонентов Vue.Если идеальный проект Vue меняется с JS на TS, этот метод очень быстрый, просто добавьтеlang=ts
и некоторые необходимые типы переменных просто прекрасны, затем используйтеVue.extend()
Просто упаковано. См. пример ниже:
JavaScript
JavaScript
TypeScript
TypeScript
Видно, что особых изменений нет -
vue-class-component
: обычно иvue-property-decorator
Используется вместе, фактическое использование используется толькоvue-property-decorator
Достаточно,vue-property-decorator
вvue-class-component
Он расширен сверху и предоставляет множество модификаторов, таких как@Prop
а также@Watch
Подождите, вы можете использовать это для написания компонентов класса, но если вы являетесь полным проектом JS для изменения TS, есть много мест, которые нужно изменить. Взгляните на следующий пример:
JavaScript
JavaScript
TypeScript
TypeScript
Видно, что изменения действительно большие
Эти два стиля написания весьма различны.Ниже приводится подробное описание конкретной реализации двух методов.
-
компоненты реквизита
-
Vue.extend()
Реализация props на самом деле ничем не отличается от JavaScript, но если вам нужны подсказки типа переменной Object, это немного отличается -
vue-class-component
Для реализации пропсов нужно ввести модификатор Prop из vue-property-decorator, который тоже очень удобен в использовании, либо воспользоваться приведенным выше примером// JavaScript props: ['isVisible', 'title', 'item', 'count', 'items'] // 如果加入了prop验证,这样写 props: { isVisible: { type: Boolean, required: true }, title: { type: [String, Number] }, item: { type: Object }, items: { type: Array, } count: { count: Number } } // TypeScript /* 这种写法没有任何改变,但是这样没有任何类型提示,这些变量能被TS识别,但是会全部被识别成any,和没类型检查一样 */ props: ['isVisible', 'title', 'item', 'count', 'items'] /* 当加入prop验证之后,TS就会提示prop类型了,如果是对象的话,还能有对象的成员提示,写法和JS写法差不多,只是对象类型(包括对象,数组和函数)的有点差别,这样写的话。*/ // 假设item对象的结构是 interface Item { key: string val: string num: number } props: { isVisible: { type: Boolean, required: true }, title: { type: [String, Number] }, item: { // 注意这里不是 // Object as Item type: Object as () => Item }, itmes: { // 注意这里不是 // Array as Array<Item> type: Array as () => Array<Item> } count: { count: Number } } // vue-class-component方式 import { Vue, Component, Prop } from 'vue-property-decorator' // 注意要加非空断言符 ! 不然会报,当然,你定义成any类型当我没说 /* [non-null-assertion-operator](https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#non-null-assertion-operator) 关于非空断言可以参考这个 */ @Prop({ required: true }) isVisible!: boolean @Prop() title!: string | number @Prop() item!: Item @Prop() items!: Array<Item> @Prop() count!: number
-
-
компонентные данные вычисляемые методы смотреть
-
Vue.extend()
На самом деле нет никакой разницы между реализацией данных и JavaScript.Если он вычисляется, то особых изменений нет.Однако те, у кого это задействовано в операции, должны указать тип возвращаемого значения, иначе будет сообщено об ошибке.Методы обрабатываются так же, как и вычисляемые, а те, которые участвуют в этой операции, должны быть помечены Тип возвращаемого значения, так же как и часы -
vue-class-component
Для реализации данных достаточно написать переменные прямо в класс.Для вычисляемого метод записи аналогичен геттеру и сеттеру.Метод методов заключается в написании методов прямо в нем.Вотч нужно ввести модификатор watch из vue-property- декоратор.//一个简单的例子 // Vue.extend() import Vue from 'vue' export default Vue.extend({ data() { return { count: 1, item: { c: '', n: '' } } }, computed: { // 需要标注有 `this` 参与运算的返回值类型 num(): number { return this.count }, name: { // 需要标注有 `this` 参与运算的返回值类型 get(): string { return this.item.n }, set(val: string) { this.item.n = val } } }, watch: { count(newVal: number, oldVal: number): void { console.log(newVal) }, 'item.n'(newVal: string, oldVal: string): void { console.log(newVal) }, item: { handler(newV, oldVal) { console.log(oldVal) }, deep: true } }, methods: { reset(): void { this.$emit('reset') }, getKey(): string { return this.item.c } } }) // vue-class-component import { Vue, Component, Watch } from 'vue-property-decorator' interface KeyValue { c: string n: string } @Component export default class Test extends Vue { // data count: number = 1 item: KeyValue = { c: '', n: '' } // computed get num(): number { return this.count } get name(): string { return this.item.n } // 注意,这里不能标返回值类型,就算写void也不行 set name(val: string) { this.item.n = val } // watch @Watch('count') watchCount(newVal: number, oldVal: number): void { console.log(newVal) } @Watch('item.n') watchName(newVal: string, oldVal: string): void { console.log(newVal) } @Watch('item', { deep: true }) watchItem(newVal: KeyValue, oldVal: KeyValue): void { console.log(newVal) } // methods reset(): void { this.$emit('reset') }, getKey(): string { return this.item.c } }
-
-
компоненты
-
Vue.extend()
компоненты и JavaScript написаны точно так же -
vue-class-component
Импортированные компоненты необходимо прописать в декораторе @Components({})// Vue.extend import Vue from 'vue' import MainHeader from './header.vue' import MainContent from './content.vue' export default Vue.extend({ components: { MainHeader, MainContent } }) // vue-class-component import { Vue, Component } from 'vue-property-decorator' import MainHeader from './header.vue' import MainContent from './content.vue' @Component({ components: { MainHeader, MainContent } }) export default class extends Vue {} ```
-
-
Миксины компонентов
-
Vue.extend()
Он не полностью реализует эффект смешивания нескольких миксинов, можно смешивать только один. Не рекомендуется писать примеси таким образом, и нельзя добиться множественного наследования. Если вам нужно попробовать этот способ письма, вы можете посмотреть на этоIssueЯ не пробовал такой подход, но кто-то писал пример, может быть использован в качестве ссылки, но я пытался не добиться успеха// ExampleMixin.vue export default Vue.extend({ data () { return { testValue: 'test' } } }) // other.vue export default Vue.extend({ mixins: [ExampleMixin], created () { this.testValue // error, testValue 不存在! } }) 我们需要稍作修改: // other.vue export default ExampleMixin.extend({ mixins: [ExampleMixin], created () { this.testValue // 编译通过 } })
-
vue-class-component
Возможность достижения множественного смешивания, аналогичного наследованию классов// mixin1.ts import Vue from 'vue' export default Vue.extend({ data () { return { valFromMixin1: 'test' } } }) // 不能是 // 这种写法会报 Mixin1 is not a constructor function type export default { data () { return { valFromMixin1: 'test' } } } // mixin2.ts import { Component, Vue } from 'vue-property-decorator' @Component export default class Mixin2 extends Vue { methodFromMixin2() {} } // test.ts import Mixin1 from './mixin1' import Mixin2 from './mixin2' import { Component, Mixins } from 'vue-property-decorator' export default class Test extends Mixins(Mixin1, Mixin2) { test() { this.methodFromMixin2() console.log(this.valFromMixin1) } } // 如果只混入一个的话,可以这样写 export default class Test extends Mixin1 {} export default class Test extends Mixin2 {} ``` 这样写不仅不会报错,而且编辑器还有提示 ![Alt ](https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2018/10/29/166be51e4d68dd4a~tplv-t2oaga2asx-image.image) 这张图可以看出,setWatch 是 BookingWatcher 里面的方法,实际上,Test 这个类并没有自身的属性,都是从 Vue,BookingWatcher 还有 TestMixins 继承过来的
-
-
функциональные компоненты
Это можно сделать только с помощью Vue.extends(), Vue-class-component бессилен, вы можете взглянуть на этоIssue
Вот способ написать функциональный компонент TypeScript
Ссылки на эту часть
Некоторые мысли об использовании TypeScript в Vue (практика)
vue официальный сайт Поддержка TypeScript
Краткое изложение некоторых проблем, возникших при разработке
-
ошибка $refs
Считается, что проблема $refs, сообщающая об ошибке, в основном встречается, если вы действительно не используете это, как показано на рисунке:
Сообщение об ошибке Свойство «размытие» не существует для типа «Vue | Element | Vue [] | Element []». Свойство «размытие» не существует для типа «Vue».
Решение: измените часть ошибки на изображении выше на
// 把这个变量改成定义成HTMLInputElement就好,这里需要用到类型断言 test() { let inputBox: HTMLInputElement = this.$refs.inputBox as HTMLInputElement inputBox.blur() }
Если есть много ссылок, и ссылка имеет свой компонент, вы можете написать так:
$refs!: {}
Таким образом, редактор также подскажет, какие методы есть в компоненте.Когда вы наберете this.$refs.header., редактор подскажет свойства и методы в компоненте Header.