一、项目需要使用typeScript,如何把js切到ts
1. 引入和使用
webpack配置
创建新项目的命令,旧版本vue init,新版本vue create ${myProject} ${template}
具体webpack配置,看前面知识更详细,下面只是简单列举的三个注意点:
a. entry - 入口
b. extentions 加上ts文件area - 用于处理尝试的数据尾缀列表
c. loaders - ts-loader,增加对于ts的处理 => 工程化
TS配置
{
"include": [
"src/*",
"src/**/*"
],
"exclude": [
"node_modules"
],
"compilerOptions": {
"strictPropertyInitialization": false,
"types": [
"node"
],
"typeRoots": [
"node_modules/@types"
],
"strict": true,
"jsx": "preserve",
"jsxFactory": "h",
"allowSyntheticDefaultImports": true,
"experimentalDecorators": true,
"strictFunctionTypes": false,
"allowJs": true,
"module": "esnext",
"target": "es5",
"moduleResolution": "node",
"noImplicitAny": true,
"lib": [
"dom",
"es5",
"es6",
"es7",
"es2015.promise"
],
"sourceMap": true,
"pretty": true
}
}
2. vue / vuex + typescript 铺开的梳理
<template>
<div>
<vueComponent />
</div>
</template>
<script lang="ts">
import Vue from 'vue'
const Component = Vue.extend({
})
import Component from 'vue-class-component'
@Component({
template: '<vueComponent />'
})
export default class myComponent extends Vue {
message: string = 'Hello'
onClick(): void {
console.log(this.message);
}
}
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}
declare module '/typings/vuePlugin.d.ts' {
interface Vue {
myProps: string
}
}
let vm = new Vue()
console.log(vm.myProps)
除了上面的声明vue模块方面,还有下面的业务模块数据方面:
import { propType } from 'vue'
interface customPayload {
str: string,
number: number,
name: string
}
const Component = Vue.extend({
props: {
name: String,
success: { type: String },
payload: {
type: Object as propType<customPayload>
},
callback: {
type: Function as propType<() => void>
}
}
})
computed: {
getMsg(): string {
return this.click() + "!"
}
}
methods: {
click(): string {
return this.message + 'zhaowa'
}
}
import { ComponentCustomProperties } from 'vue'
declare module '@vue/runtime-core' {
interface State {
count: number
}
interface ComponentCustomProperties {
$store: Store<State>
}
}
import { InjectionKey } from 'vue'
import {
createStore,
Store
} from 'vuex'
export interface State {
count: number
}
export const key: InjectionKey<Store<State>> = Symbol()
export const store = createStore<State>({
state: {
count: 0
}
})
import { createApp } from 'vue'
import { store, key } from './store'
const app = createApp({
})
app.use(store, key)
app.mount('#app')
import { useStore } from 'vuex'
import { key } from './store'
export default {
const store = useStore(key)
store.state.count
}
import { State, Action, Getter } from "vuex-class"
export default class App extends Vue {
@State login: boolean;
@Action setInit: () => void;
get isLogin: boolean;
mounted() {
this.setInit();
}
}
</script>
3. 正式代码
以下列出主要的文件,不包括配置文件,此例子功能不重要,重要的是为了构建整体脉络,让自己体会引入ts之后,各个文件有哪些改变,以及这些改变如何彼此打配合,方便以后真实开发的流畅性。
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}
declare namespace StoreState {
export interface plate {
url: string,
imgUrl: string,
name: string
}
export interface prod {
url: string,
imgUrl: string,
prodName: string,
desc: string,
price: string
}
}
declare namespace Ajax {
export interface AjaxResponse {
data: AjaxResponse;
}
export interface AjaxResponse {
code: number;
result: any;
message?: string;
}
}
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import './assets/mock'
Vue.config.productionTip = false
const app: Vue = new Vue({
el: '#app',
router,
store,
render: h => h(App)
})
export default app
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
@Component
export default class App extends Vue {}
</script>
<style lang="stylus">
body {
font-size: 14px;
margin: 0;
}
.divider {
height: 10px;
background-color: #f0f0f0;
}
</style>
import Vue, { AsyncComponent } from 'vue'
import Router, { RouteConfig } from 'vue-router'
const main: AsyncComponent = (): any => import('@/pages/main.vue')
Vue.use(Router)
const routes: RouteConfig[] = [
{
path: '/',
redirect: '/index'
},
{
path: '/index',
name: 'main',
component: main
}
]
const router: Router = new Router({
mode: 'history',
base: '/',
routes
})
export default router
<template>
<div class="main">
<div class="header">上海</div>
<div class="main-content">
<plates></plates>
<prodList></prodList>
</div>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
import { State, Action, Getter } from "vuex-class";
import prodList from '../components/prodList.vue';
import plates from '../components/plates.vue';
@Component({
components: {
prodList,
plates
}
})
export default class App extends Vue {
@Action initAjax: () => void;
mounted() {
this.initAjax();
}
}
</script>
<style lang="stylus">
.main {
.header {
background-color: #ff1395;
padding: 20px;
width: 100%;
}
.main-content {
padding: 10px;
}
}
</style>
<template>
<div class="plates">
<div class="plate-flex" v-for="(page, index) in plates" :key="index">
<div class="plate" v-for="(module, index) in page" :key="index">
<img :src="module.imgUrl" />
<div class="name"> {{ module.name }} </div>
</div>
</div>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
import { State, Action } from "vuex-class";
@Component({
name: 'plates'
})
export default class plates extends Vue {
@State plates: StoreState.plate[]
}
</script>
<style lang="stylus">
.plates {
.plate-flex {
display: flex;
.plate {
flex: 1;
text-align: center;
img {
height: 30px;
width: 30px;
}
.name {
// font-size:
}
}
}
}
</style>
<template>
<div class="prod-list">
<div class="prod" v-for="(prod, index) in products" :key="index">
<div class="prod-logo">
<img :src="prod.imgUrl" alt="img">
</div>
<div class="content">
{{prod.prodName}} - {{prod.desc}} - {{prod.price}}
</div>
</div>
</div>
</template>
<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
import { State } from "vuex-class";
@Component
export default class prodList extends Vue {
@State prodList: StoreState.prod[]
get products(): StoreState.prod[] {
const prodList = this.prodList;
return prodList;
}
}
</script>
<style lang="stylus">
.prod-list {
padding-top: 20px;
.prod {
padding: 0 10px 10px 10px;
display: flex;
}
.prod-logo {
position: relative;
img {
width: 100px;
height: 120px;
}
.content {
}
}
}
</style>
import { ActionTree } from 'vuex'
import axios from 'axios'
import TYPES from './types'
const actions: ActionTree<any, any> = {
async initAjax({ dispatch }) {
dispatch('getPlates')
dispatch('getProdList')
},
async getPlates({ state, commit }) {
const res: Ajax.AjaxResponse = await axios.get('/plates').then(
(res) => res.data
).catch(
(e: string) => console.log(e)
)
if (res && res.code == 200) {
commit(TYPES.SET_PLATES, res.result.list)
}
},
async getProdList({ state, commit }) {
const res: Ajax.AjaxResponse = await axios.get('/prodList').then(
(res) => res.data
).catch(
(e: string) => console.log(e)
)
if (res && res.code == 200) {
commit(TYPES.SET_PROD_LIST, res.result.list)
}
}
}
export default actions
import Vue from 'vue'
import Vuex, { ActionTree, MutationTree } from 'vuex'
import actions from './actions'
import mutations from './mutations'
Vue.use(Vuex)
interface State {
plates: StoreState.plate[],
prodList: StoreState.prod[]
}
let state: State = {
plates: [],
prodList: []
}
export default new Vuex.Store({
state,
actions,
mutations
})
import TYPES from './types'
import { MutationTree } from 'vuex'
const mutations: MutationTree<any> = {
[TYPES.SET_PLATES](state, plates): void {
state.plates = plates
},
[TYPES.SET_PROD_LIST](state, prodList): void {
state.prodList = prodList
}
}
export default mutations
export default {
SET_PLATES: 'SET_PLATES',
SET_PROD_LIST: 'SET_PROD_LIST'
}