webpack 完整配置能夠參考 typescript-vue-eslint-starter [ github.com/vok123/type… ]javascript
歡迎提建議,若是以爲有用的給個star哈~vue
↓↓↓↓↓↓高能時刻↓↓↓↓↓↓java
開局一隻蔡徐坤, 漲薪全靠vue + ts [www.bilibili.com/video/av503…]node
npm i -D @vue/cli-plugin-eslint @vue/eslint-config-standard @vue/eslint-config-typescript eslint eslint-loader eslint-plugin-node eslint-plugin-vue typescript ts-loader
複製代碼
npm i -S vue-class-component vue-property-decorator vuex-class
複製代碼
完整webpack配置 [github.com/vok123/type…]webpack
module: {
rules: [
{
test: /\.ts(x)?$/,
loader: 'ts-loader',
exclude: /node_modules/,
options: {
appendTsSuffixTo: [/\.vue$/],
transpileOnly: true,
happyPackMode: false
}
},
{
test: /\.(js|vue|ts|tsx|jsx)$/,
enforce: 'pre',
exclude: /node_modules/,
loader: 'eslint-loader',
options: {
fix: false,
extensions: ['.js', '.jsx', '.vue', '.ts', '.tsx'],
cache: false,
emitWarning: true,
emitError: false
}
}
];
}
複製代碼
module.exports = {
plugins: ['vue', '@typescript-eslint'],
parserOptions: {
parser: '@typescript-eslint/parser',
ecmaVersion: 2017,
sourceType: 'module'
},
root: true,
env: {
node: true
},
extends: [
'plugin:vue/base',
'plugin:@typescript-eslint/recommended',
'plugin:vue/essential',
'@vue/standard',
'@vue/typescript'
],
rules: {
// eslint rules
'one-var': 0,
'arrow-parens': 0,
'generator-star-spacing': 0,
'no-debugger': 0,
'no-console': 0,
semi: [2, 'always'],
'no-extra-semi': 2,
'space-before-function-paren': 0,
eqeqeq: 0,
'spaced-comment': 0,
'no-useless-escape': 0,
'no-tabs': 0,
'no-mixed-spaces-and-tabs': 0,
'new-cap': 0,
camelcase: 0,
'no-new': 0,
indent: 'off',
// typescript-eslint rules
'@typescript-eslint/indent': ['error', 2],
'@typescript-eslint/explicit-function-return-type': 0
}
};
複製代碼
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"strict": true,
"jsx": "preserve",
"importHelpers": true,
"moduleResolution": "node",
"experimentalDecorators": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"sourceMap": true,
"allowJs": true,
"baseUrl": ".",
"types": ["webpack-env", "node"],
"paths": {
"@/*": ["src/*"]
},
"lib": ["esnext", "dom", "dom.iterable", "scripthost"]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": ["node_modules"]
}
複製代碼
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}
複製代碼
declare module "vue/types/vue" {
interface Vue {
$message: (msg: string): void;
$balala: string;
}
}
// 在組件中使用
this.$balala
this.$message('Hello world');
複製代碼
declare module "vue/types/options" {
interface ComponentOptions<V extends Vue> {
i18n: any
}
}
// 使用
new Vue({
i18n, ...
});
複製代碼
// 聲明 element-ui
declare module 'element-ui'
// 聲明 axios
declare module 'axios' {
import Axios from 'axios/index';
export default Axios;
}
複製代碼
裝飾器 | 用途 | 描述 |
---|---|---|
Component | 聲明class組件 | 只要是個組件都必須加該裝飾器 |
Prop | 聲明props | 對應普通組件聲明中的props屬性 |
Watch | 聲明監聽器 | 對應普通組件聲明中的watch屬性 |
Mixins | 混入繼承 | 對應普通組件聲明中的mixins屬性 |
Emit | 子組件向父組件值傳遞 | 對應普通this.$emit() |
Inject | 接收祖先組件傳遞的值 | 對應普通組件聲明中的inject屬性 |
Provide | 祖先組件向其全部子孫後代注入一個依賴 | 對應普通組件聲明中的provide屬性 |
用法ios
// javascript
<script>
export default {
beforeCreate() {},
created() {},
beforeMount() {},
mounted() {},
beforeUpdate() {},
updated() {},
activated() {},
deactivated() {},
beforeDestroy() {},
destroyed() {},
errorCaptured() {}
}
</script>
// --------typescript--------
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
@Component
export default class App extends Vue {
beforeCreate() {}
created() {}
beforeMount() {}
mounted() {}
beforeUpdate() {}
updated() {}
activated() {}
deactivated() {}
beforeDestroy() {}
destroyed() {}
errorCaptured() {}
}
</script>
複製代碼
// javascript
import helloWorld from './helloWorld.vue';
export default {
components: {
helloWorld
}
}
// --------typescript--------
import helloWorld from './helloWorld.vue';
import { Component, Vue } from 'vue-property-decorator';
@Component({
components: {
helloWorld
}
})
export default class App extends Vue {}
複製代碼
// javascript
export default {
props: {
msg: {
type: String,
default: 'Hello world',
required: true,
validator: (val) => (val.length > 2)
}
}
}
// --------typescript--------
import { Component, Vue, Prop } from 'vue-property-decorator';
@Component
export default class HelloWorld extends Vue {
@Prop({
type: String,
default: 'Hello world',
required: true,
validator: (val) => (val.length > 2)
}) msg!: string
}
複製代碼
// javascript
export default {
data() {
return {
value: ''
}
},
watch: {
value: {
handler() {
console.log(this.value);
},
deep: true,
immediate: true
}
}
}
// --------typescript--------
import { Component, Vue, Watch } from 'vue-property-decorator';
@Component
export default class App extends Vue {
value: string = ''
@Watch('value', { deep: true, immediate: true })
valueWatch() {
console.log(this.value);
}
}
複製代碼
// javascript
// -info.js
export default {
methods: {
mixinsShow() {
console.log('徐蔡坤');
}
}
}
// -hello-world.vue
import mixinsInfo from './info.js';
export default {
mixins: [mixinsInfo]
mounted() {
this.mixinsShow(); // 徐蔡坤
}
}
// --------typescript--------
// -info.ts
import { Component, Vue } from 'vue-property-decorator';
@Component
export default class MixinsInfo extends Vue {
mixinsShow() {
console.log('徐蔡坤');
}
}
// -hello-world.vue
import { Component, Vue, Mixins } from 'vue-property-decorator';
import mixinsInfo from './info.ts';
@Component
export default class HelloWorld extends Mixins(mixinsInfo) {
mounted() {
this.mixinsShow(); // 徐蔡坤
}
}
複製代碼
// javascript
// -children.vue
<template>
<button @click="$emit('submit', '唱, 跳')">提交</button>
</template>
// -parent.vue
<template>
<children @submit="submitHandle"/>
</template>
import children from './children.vue';
export default {
components: {
children
},
methods: {
submitHandle(msg) {
console.log(msg); // 唱, 跳
}
}
}
// --------typescript--------
// -children.vue
<template>
<button @click="submit">提交</button>
</template>
<script lang="ts">
import { Component, Vue, Emit } from 'vue-property-decorator';
@Component
export default class Children extends Vue {
@Emit()
submit() {
return '唱, 跳';
}
}
</script>
// -parent.vue
<template>
<children @submit="submitHandle"/>
</template>
<script lang="ts">
import children from './children.vue';
import { Component, Vue } from 'vue-property-decorator';
@Component({
components: {
children
}
})
export default class Parent extends Vue {
submitHandle(msg: string) {
console.log(msg); // 唱, 跳
}
}
</script>
複製代碼
// javascript
// -children.vue
export default {
inject: ['root'],
mounted() {
console.log(this.root.name); // rap, 籃球
}
}
// -parent.vue
<template>
<children />
</template>
import children from './children.vue';
export default {
components: {
children
},
data() {
return {
name: 'rap, 籃球'
};
},
provide() {
return {
root: this
};
}
}
// --------typescript--------
// -children.vue
<script lang="ts">
import { Component, Vue, Inject } from 'vue-property-decorator';
@Component
export default class Children extends Vue {
@Inject() root!: any
mounted() {
console.log(this.root.name); // rap, 籃球
}
}
</script>
// -parent.vue
<template>
<children />
</template>
<script lang="ts">
import children from './children.vue';
import { Component, Vue, Provide } from 'vue-property-decorator';
@Component({
components: {
children
}
})
export default class Parent extends Vue {
name: string = 'rap, 籃球'
@Provide()
root = this.getParent();
getParent() {
return this;
}
}
</script>
複製代碼
// javascript
export default {
data() {
return {
hobby: '唱, 跳, rap, 籃球'
};
},
computed: {
msg() {
return '我也會' + this.hobby;
}
},
mounted() {
console.log(this.msg); // 我也會唱, 跳, rap, 籃球
}
}
// --------typescript--------
// -hello-world.vue
import { Component, Vue } from 'vue-property-decorator';
@Component
export default class HelloWorld extends Vue {
hobby: string = '唱, 跳, rap, 籃球'
get msg() {
return '我也會' + this.hobby;
}
mounted() {
console.log(this.msg); // 我也會唱, 跳, rap, 籃球
}
}
複製代碼
裝飾器 | 用途 |
---|---|
State | 獲取vuex state |
Getter | 獲取vuex getter |
Mutation | 獲取vuex mutation |
Action | 獲取vuex actions |
vuex typescript 基礎定義git
// -store/store.ts
import Vue from 'vue';
import Vuex, { StoreOptions } from 'vuex';
import user from './modules/user';
Vue.use(Vuex);
interface RootState {
version: string;
}
const store: StoreOptions<RootState> = {
strict: true,
state: {
version: '1.0.0'
},
modules: {
user
}
};
export default new Vuex.Store<RootState>(store);
// -store/modules/user.ts
import { Module } from 'vuex';
export interface UserInfo {
uId: string;
name: string;
age: number;
}
interface UserState {
userInfo: UserInfo;
}
const user: Module<UserState, any> = {
namespaced: true,
state: {
userInfo: {
uId: '',
name: '',
age: 0
}
},
getters: {
isLogin(state) {
return !!state.userInfo.uId;
}
},
mutations: {
updateUserInfo(state, userInfo: UserInfo): void {
Object.assign(state.userInfo, userInfo);
}
},
actions: {
async getUserInfo({ commit }): Promise<void> {
let { userInfo } = await getUserInfo();
commit('updateUserInfo', userInfo);
}
}
};
export default user;
複製代碼
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { State, Getter, Action } from 'vuex-class';
import { UserInfo } from './store/modules/user';
@Component
export default class App extends Vue {
@State('version') version!: string
@State('userInfo', { namespace: 'user' }) userInfo!: UserInfo
@Getter('isLogin', { namespace: 'user' }) isLogin!: boolean
@Action('getUserInfo', { namespace: 'user' }) getUserInfo!: Function
mounted() {
this.getUserInfo();
console.log(this.version); // 1.0.0
}
}
</script>
複製代碼
// test.ts
import store from './store/store';
if (store.getters['user/isLogin'] === false) {
console.log('未登陸');
}
複製代碼
默認狀況下typescript在轉換語法爲es3或者es5時並不會轉換ES6 Api, 例如(Object.values, Array.fill ...) 在這種狀況下咱們能夠使用 (ts-polyfill) [github.com/ryanelian/t…] 定向指定須要轉換的apigithub