摘要:靜態(tài)類(lèi)型系統(tǒng)能幫助你有效防止許多潛在的運(yùn)行時(shí)錯(cuò)誤,而且隨著你的應(yīng)用日漸豐滿(mǎn)會(huì)更加顯著。選擇,會(huì)生成符合規(guī)范的文件,使用,會(huì)生成滿(mǎn)足規(guī)范的文件,使用會(huì)生成使用的的代碼。使用或者是會(huì)生產(chǎn)包含特性的代碼。
靜態(tài)類(lèi)型系統(tǒng)能幫助你有效防止許多潛在的運(yùn)行時(shí)錯(cuò)誤,而且隨著你的應(yīng)用日漸豐滿(mǎn)會(huì)更加顯著。這就是為什么 Vue 不僅僅為 Vue core 提供了針對(duì) TypeScript 的官方類(lèi)型聲明,還為 Vue Router 和 Vuex 也提供了相應(yīng)的聲明文件TsConfig配置
{ "compilerOptions": { // ts 文件編譯成 js 文件的時(shí)候,同時(shí)生成對(duì)應(yīng)的 map 文件 "sourceMap": true, "strict": true, "strictNullChecks": true, // 當(dāng)表達(dá)式和申明 類(lèi)型為any時(shí),是否需要發(fā)出警告,設(shè)置true,則不警告 "noImplicitAny": true, // 設(shè)置為true時(shí),如果不是函數(shù)中的所有路徑都有返回值,則提示Error "noImplicitReturns": true, // module 用于指定模塊的代碼生成規(guī)則,可以使用 commonjs 、 amd 、 umd 、 system 、 es6 、 es2015 、 none 這些選項(xiàng)。 // 選擇commonJS,會(huì)生成符合commonjs規(guī)范的文件,使用amd,會(huì)生成滿(mǎn)足amd規(guī)范的文件,使用system會(huì)生成使用ES6的 // system.import的代碼。使用es6或者是es2015會(huì)生產(chǎn)包含ES6特性的代碼。 "module": "es2015", "moduleResolution": "node", // 設(shè)置為true時(shí),則允許從沒(méi)有默認(rèn)導(dǎo)出的模塊中默認(rèn)導(dǎo)入(也就是不做檢查) "allowSyntheticDefaultImports": true, // 設(shè)置為true,則支持ES7的裝飾器特性 "experimentalDecorators": true, // target 用于指定生成代碼的兼容版本,可以從es3,es5,es2015,es6中選擇一個(gè),如果不設(shè)置,默認(rèn)生產(chǎn)的代碼兼容到es3 "target": "es5" }, "include": [ "./src/**/*" ] }
配置參考:
官方文檔tsconfig解析
tsconfig的JSON文檔
Webpack的基礎(chǔ)配置一覽每個(gè)項(xiàng)目最重要的一部分個(gè)人感覺(jué)是webpack的配置,只有配置好webpack部分后續(xù)才能順利進(jìn)行開(kāi)發(fā)
這里webpack使用了4.+的版本,所以算是體驗(yàn)了較為新的webpack,其中和舊版的有些區(qū)別,這里不做介紹
先貼出webpack的配置代碼
const path = require("path") const webpack = require("webpack") const VueLoaderPlugin = require("vue-loader/lib/plugin") module.exports = { mode: process.env.NODE_ENV === "production" ? "production" : "development", entry: "./src/index.ts", output: { path: path.resolve(__dirname, "./dist"), publicPath: "/dist/", filename: "build.js" }, module: { rules: [ { test: /.vue$/, loader: "vue-loader", options: { loaders: { "scss": "vue-style-loader!css-loader!sass-loader", "sass": "vue-style-loader!css-loader!sass-loader?indentedSyntax", } } }, { test: /.tsx?$/, loader: "ts-loader", exclude: /node_modules/, options: { transpileOnly: true, appendTsSuffixTo: [/.vue$/] } } ] }, resolve: { extensions: [".ts", ".js", ".vue", ".josn"], alias: { "vue$": "vue/dist/vue.esm.js" } }, devServer: { contentBase: "./public", host: "localhost", port: "8080", open: true, hot: true, inline: true, historyApiFallback: true, noInfo: true }, performance: { hints: false }, devtool: "#eval-source-map", plugins: [ new VueLoaderPlugin() ] } if (process.env.NODE_ENV === "production") { module.exports.devtool = "#source-map" module.exports.plugins = (module.exports.plugins || []).concat([ new webpack.DefinePlugin({ "process.env": { NODE_ENV: ""production"" } }), new webpack.optimize.UglifyJsPlugin({ sourceMap: true, compress: { warnings: false } }), new webpack.LoaderOptionsPlugin({ minimize: true }) ]) } else { module.exports.plugins = (module.exports.plugins || []).concat([ new webpack.HotModuleReplacementPlugin() ]) }
注意點(diǎn):
vue-loader v15需要在webpack插件中添加VueLoaderPlugin插件
webpack4.+需要指定mode,開(kāi)發(fā)模式還是生產(chǎn)模式
注意ts-loader的配置
這里只是簡(jiǎn)單進(jìn)行webpack配置,沒(méi)有太完整地根據(jù)完整的項(xiàng)目來(lái)進(jìn)行配置,只是簡(jiǎn)單配置了生產(chǎn)環(huán)境下的代碼混淆壓縮,以及對(duì)應(yīng)的開(kāi)發(fā)服務(wù)器和熱更新等,有需要其他功能擴(kuò)展的自行配置。
Vue環(huán)境搭建配置 vue-shims.d.ts的添加這個(gè)是比較重要的一個(gè)配置,該文件需要放到vue的入口文件中,具體的d.ts代碼如下:
declare module "*.vue" { import Vue from "vue" export default Vue }
目的是讓ts能夠識(shí)別到vue的靜態(tài)類(lèi)型
vue的入口文件index.ts:
import Vue from "vue" import App from "./App.vue" // vuex部分 import store from "./store" new Vue({ el: "#app", store, render: h => h(App), })
入口文件跟普通的js寫(xiě)法沒(méi)有太多的區(qū)別,只是文件類(lèi)型為ts。
開(kāi)始寫(xiě)vue的單文件頁(yè)面和組件 單文件頁(yè)面模板...
主要是在script項(xiàng)中把lang寫(xiě)為ts類(lèi)型
使用裝飾器來(lái)實(shí)現(xiàn)組件和頁(yè)面這里我們主要使用兩個(gè)裝飾器庫(kù)vue-property-decorator 和 vuex-class, vue-property-decorator其是基于vue-class-得component的基礎(chǔ)擴(kuò)展修改的。
大致了解一下vue-property-decorator的裝飾器的用法
一共有七個(gè)裝飾器:
@Emit
@Inject
@Model
@Prop
@Provide
@Watch
@Component (exported from vue-class-component)
這里使用vue-property-decorator的例子來(lái)做解析
import { Component, Emit, Inject, Model, Prop, Provide, Vue, Watch } from "vue-property-decorator" const s = Symbol("baz") @Component export class MyComponent extends Vue { @Emit() addToCount(n: number){ this.count += n } @Emit("reset") resetCount(){ this.count = 0 } @Inject() foo: string @Inject("bar") bar: string @Inject({from: "optional", default: "default"}) optional: string @Inject(s) baz: string @Model("change") checked: boolean @Prop() propA: number @Prop({ default: "default value" }) propB: string @Prop([String, Boolean]) propC: string | boolean @Provide() foo = "foo" @Provide("bar") baz = "bar" @Watch("child") onChildChanged(val: string, oldVal: string) { } @Watch("person", { immediate: true, deep: true }) onPersonChanged(val: Person, oldVal: Person) { } }
相當(dāng)于js的寫(xiě)法:
const s = Symbol("baz") export const MyComponent = Vue.extend({ name: "MyComponent", inject: { foo: "foo", bar: "bar", "optional": { from: "optional", default: "default" }, [s]: s }, model: { prop: "checked", event: "change" }, props: { ? ?checked: Boolean, ? ?propA: Number, propB: { type: String, default: "default value" }, propC: [String, Boolean], }, data () { return { foo: "foo", baz: "bar" } }, provide () { return { foo: this.foo, bar: this.baz } }, methods: { addToCount(n){ this.count += n this.$emit("add-to-count", n) }, resetCount(){ this.count = 0 this.$emit("reset") }, onChildChanged(val, oldVal) { }, onPersonChanged(val, oldVal) { } }, watch: { "child": { handler: "onChildChanged", immediate: false, deep: false }, "person": { handler: "onPersonChanged", immediate: true, deep: true } } })
相信通過(guò)以上的例子我們很容易就看出各個(gè)裝飾器如何去使用,這里就不再做太多的解釋。
再看一下vuex-class的使用方法
同樣舉例官方的使用列子
import Vue from "vue" import Component from "vue-class-component" import { State, Getter, Action, Mutation, namespace } from "vuex-class" const someModule = namespace("path/to/module") @Component export class MyComp extends Vue { @State("foo") stateFoo @State(state => state.bar) stateBar @Getter("foo") getterFoo @Action("foo") actionFoo @Mutation("foo") mutationFoo @someModule.Getter("foo") moduleGetterFoo @State foo @Getter bar @Action baz @Mutation qux created () { this.stateFoo // -> store.state.foo this.stateBar // -> store.state.bar this.getterFoo // -> store.getters.foo this.actionFoo({ value: true }) // -> store.dispatch("foo", { value: true }) this.mutationFoo({ value: true }) // -> store.commit("foo", { value: true }) this.moduleGetterFoo // -> store.getters["path/to/module/foo"] } }Vuex的配置 store的入口
import Vue from "vue" import Vuex, { StoreOptions } from "vuex" import { RootState } from "./modules/types" import { profile } from "./modules/profile" Vue.use(Vuex) const store: StoreOptions= { state: { version: "v1.0.0" }, modules: { profile } } export default new Vuex.Store (store);
這里RootState只是用于留空,目的是為了注入全局的store,區(qū)別于modules的狀態(tài)
vuex的modules的配置寫(xiě)一個(gè)全局類(lèi)型聲明
export interface RootState { version: string; }
version字段就是我們剛才在RootState中定義的字段
定義模板profile
profile模塊的類(lèi)型聲明:
export interface ProfileState { firstName: string lastName: string }
profile的模塊實(shí)現(xiàn):
import { RootState } from "../types" import { Module } from "vuex" import { ProfileState } from "./types" import { GetterTree, ActionTree, MutationTree } from "vuex" import axios, { AxiosPromise } from "axios" const state: ProfileState = { firstName: "", lastName: "" } const getters: GetterTree= { firstName(state) : string { return state.firstName }, lastName(state) : string { return state.lastName } } const actions: ActionTree = { fetchName({ commit }, id: number): AxiosPromise { console.log("action:", id) return axios.request({ url: "https://www.apiopen.top/satinCommentApi?id=27610708&page=1" }).then(res => { commit("setProfile", { firstName: "lin", lastName: "guangyu" }) return res }).catch(err => { return err }) } } const mutations: MutationTree = { setProfile(state, payload: ProfileState) { state.firstName = payload.firstName state.lastName = payload.lastName } } const namespaced: boolean = true; export const profile: Module = { namespaced, state, getters, actions, mutations };
這里我們就完成了Vuex的配置了,就可以結(jié)合裝飾器對(duì)vuex進(jìn)行調(diào)用,而且具有靜態(tài)類(lèi)型提示,十分方便。
完成了這一系列的配置我們的嘗試已經(jīng)完成,自己寫(xiě)了個(gè)簡(jiǎn)單的demo,有興趣可以觀看github怎么配置。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/95289.html
摘要:哪吒別人的看法都是狗屁,你是誰(shuí)只有你自己說(shuō)了才算,這是爹教我的道理。哪吒去他個(gè)鳥(niǎo)命我命由我,不由天是魔是仙,我自己決定哪吒白白搭上一條人命,你傻不傻敖丙不傻誰(shuí)和你做朋友太乙真人人是否能夠改變命運(yùn),我不曉得。我只曉得,不認(rèn)命是哪吒的命。 showImg(https://segmentfault.com/img/bVbwiGL?w=900&h=378); 出處 查看github最新的Vue...
摘要:五六月份推薦集合查看最新的請(qǐng)點(diǎn)擊集前端最近很火的框架資源定時(shí)更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥(niǎo)雀呼晴,侵曉窺檐語(yǔ)。葉上初陽(yáng)乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門(mén),久作長(zhǎng)安旅。五月漁郎相憶否。小楫輕舟,夢(mèng)入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請(qǐng)::點(diǎn)擊::集web前端最近很火的vue2框架資源;定時(shí)更新,歡迎 Star 一下。 蘇...
摘要:五六月份推薦集合查看最新的請(qǐng)點(diǎn)擊集前端最近很火的框架資源定時(shí)更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥(niǎo)雀呼晴,侵曉窺檐語(yǔ)。葉上初陽(yáng)乾宿雨,水面清圓,一一風(fēng)荷舉。家住吳門(mén),久作長(zhǎng)安旅。五月漁郎相憶否。小楫輕舟,夢(mèng)入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請(qǐng)::點(diǎn)擊::集web前端最近很火的vue2框架資源;定時(shí)更新,歡迎 Star 一下。 蘇...
閱讀 1978·2021-11-23 09:51
閱讀 889·2021-11-19 09:40
閱讀 838·2021-10-27 14:20
閱讀 5033·2021-10-09 09:52
閱讀 3310·2021-10-09 09:44
閱讀 1739·2021-10-08 10:05
閱讀 5109·2021-09-09 11:47
閱讀 3488·2019-08-30 12:47