{"id":13500149,"url":"https://github.com/Microsoft/TypeScript-Vue-Starter","last_synced_at":"2025-03-29T05:33:02.738Z","repository":{"id":43894568,"uuid":"90786593","full_name":"microsoft/TypeScript-Vue-Starter","owner":"microsoft","description":"A starter template for TypeScript and Vue with a detailed README describing how to use the two together.","archived":true,"fork":false,"pushed_at":"2019-10-09T00:06:11.000Z","size":167,"stargazers_count":4446,"open_issues_count":34,"forks_count":590,"subscribers_count":130,"default_branch":"master","last_synced_at":"2025-03-21T23:42:51.292Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/microsoft.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-05-09T19:59:14.000Z","updated_at":"2025-03-19T09:05:40.000Z","dependencies_parsed_at":"2022-09-05T02:40:32.569Z","dependency_job_id":null,"html_url":"https://github.com/microsoft/TypeScript-Vue-Starter","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microsoft%2FTypeScript-Vue-Starter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microsoft%2FTypeScript-Vue-Starter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microsoft%2FTypeScript-Vue-Starter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microsoft%2FTypeScript-Vue-Starter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/microsoft","download_url":"https://codeload.github.com/microsoft/TypeScript-Vue-Starter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246145012,"owners_count":20730494,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T22:00:51.815Z","updated_at":"2025-03-29T05:32:58.493Z","avatar_url":"https://github.com/microsoft.png","language":"JavaScript","readme":"This repo is deprecated, it was created in the days before Vue shipped with TypeScript out of the box. Now the \r\nbest path to get started is through [the official CLI](https://cli.vuejs.org). We'll keep this repo around as\r\na useful archive.\r\n\r\n---\r\n\r\n# TypeScript Vue Starter\r\n\r\nThis quick start guide will teach you how to get [TypeScript](http://www.typescriptlang.org/) and [Vue](https://vuejs.org) working together.\r\nThis guide is flexible enough that any steps here can be used to integrate TypeScript into an existing Vue project.\r\n\r\n# Before you begin\r\n\r\nIf you're new to Typescript and Vue, here are few resources to get you up and running:\r\n\r\n## TypeScript\r\n  * [Up and Running with TypeScript](https://egghead.io/courses/up-and-running-with-typescript)\r\n  * [TypeScript 5 Minute Tutorial](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html)\r\n  * [Documentation](http://www.typescriptlang.org/docs/home.html)\r\n  * [TypeScript GitHub](https://github.com/Microsoft/TypeScript)\r\n\r\n## Vue\r\n  * [Vuejs Guide](https://vuejs.org/v2/guide/)\r\n  * [Vuejs Tutorial](https://www.youtube.com/playlist?list=PL4cUxeGkcC9gQcYgjhBoeQH7wiAyZNrYa)\r\n  * [Build an App with Vue.js](https://scotch.io/tutorials/build-an-app-with-vue-js-a-lightweight-alternative-to-angularjs)\r\n\r\n\r\n\r\n# Initialize your project\r\n\r\nLet's create a new package.\r\n\r\n```sh\r\nmkdir typescript-vue-tutorial\r\ncd typescript-vue-tutorial\r\n```\r\n\r\nNext, we'll scaffold our project in the following way:\r\n\r\n```txt\r\ntypescript-vue-tutorial/\r\n├─ dist/\r\n└─ src/\r\n   └─ components/\r\n```\r\n\r\nTypeScript files will start out in your `src` folder, run through the TypeScript compiler, then webpack, and end up in a `bundle.js` file in `dist`.\r\nAny components that we write will go in the `src/components` folder.\r\n\r\nLet's scaffold this out:\r\n\r\n```shell\r\nmkdir src\r\ncd src\r\nmkdir components\r\ncd ..\r\n```\r\n\r\nWebpack will eventually generate the `dist` directory for us.\r\n\r\n# Initialize the project\r\n\r\nNow we'll turn this folder into an npm package.\r\n\r\n```shell\r\nnpm init\r\n```\r\n\r\nYou'll be given a series of prompts.\r\nYou can use the defaults except for your entry point.\r\nYou can always go back and change these in the `package.json` file that's been generated for you.\r\n\r\n# Install our dependencies\r\n\r\nEnsure TypeScript, Webpack, Vue and the necessary loaders are installed.\r\n\r\n```sh\r\nnpm install --save-dev typescript webpack webpack-cli ts-loader css-loader vue vue-loader vue-template-compiler\r\n```\r\n\r\nWebpack is a tool that will bundle your code and optionally all of its dependencies into a single `.js` file.\r\nWhile you don't need to use a bundler like Webpack or Browserify, these tools will allow us to use `.vue` files which we'll cover in a bit.\r\n\r\nWe didn't need to [add `.d.ts` files](https://www.typescriptlang.org/docs/handbook/declaration-files/consumption.html), but if we were using a package which didn't ship declaration files, we'd need to install the appropriate `@types/` package.\r\n[Read more about using definition files in our documentation](https://www.typescriptlang.org/docs/handbook/declaration-files/consumption.html).\r\n\r\n# Add a TypeScript configuration file\r\n\r\nYou'll want to bring your TypeScript files together - both the code you'll be writing as well as any necessary declaration files.\r\n\r\nTo do this, you'll need to create a `tsconfig.json` which contains a list of your input files as well as all your compilation settings.\r\nSimply create a new file in your project root named `tsconfig.json` and fill it with the following contents:\r\n\r\nYou can easily create `tsconfig.json` this command.\r\n\r\n```\r\ntsc --init\r\n```\r\n\r\n```json\r\n{\r\n    \"compilerOptions\": {\r\n        \"outDir\": \"./built/\",\r\n        \"sourceMap\": true,\r\n        \"strict\": true,\r\n        \"noImplicitReturns\": true,\r\n        \"module\": \"es2015\",\r\n        \"moduleResolution\": \"node\",\r\n        \"target\": \"es5\"\r\n    },\r\n    \"include\": [\r\n        \"./src/**/*\"\r\n    ]\r\n}\r\n```\r\n\r\nNotice the `strict` flag is set to true.\r\nAt the very least, TypeScript's `noImplicitThis` flag will need to be turned on to leverage Vue's declaration files, but `strict` gives us that and more (like `noImplicitAny` and `strictNullChecks`).\r\nWe strongly recommend using TypeScript's stricter options for a better experience.\r\n\r\n# Adding Webpack\r\n\r\nWe'll need to add a `webpack.config.js` to bundle our app.\r\n\r\n```js\r\nvar path = require('path')\r\nvar webpack = require('webpack')\r\nconst VueLoaderPlugin = require('vue-loader/lib/plugin')\r\n\r\nmodule.exports = {\r\n  entry: './src/index.ts',\r\n  output: {\r\n    path: path.resolve(__dirname, './dist'),\r\n    publicPath: '/dist/',\r\n    filename: 'build.js'\r\n  },\r\n  module: {\r\n    rules: [\r\n      {\r\n        test: /\\.vue$/,\r\n        loader: 'vue-loader',\r\n        options: {\r\n          loaders: {\r\n            // Since sass-loader (weirdly) has SCSS as its default parse mode, we map\r\n            // the \"scss\" and \"sass\" values for the lang attribute to the right configs here.\r\n            // other preprocessors should work out of the box, no loader config like this necessary.\r\n            'scss': 'vue-style-loader!css-loader!sass-loader',\r\n            'sass': 'vue-style-loader!css-loader!sass-loader?indentedSyntax',\r\n          }\r\n          // other vue-loader options go here\r\n        }\r\n      },\r\n      {\r\n        test: /\\.tsx?$/,\r\n        loader: 'ts-loader',\r\n        exclude: /node_modules/,\r\n        options: {\r\n          appendTsSuffixTo: [/\\.vue$/],\r\n        }\r\n      },\r\n      {\r\n        test: /\\.(png|jpg|gif|svg)$/,\r\n        loader: 'file-loader',\r\n        options: {\r\n          name: '[name].[ext]?[hash]'\r\n        }\r\n      },\r\n      {\r\n        test: /\\.css$/,\r\n        use: [\r\n          'vue-style-loader',\r\n          'css-loader'\r\n        ]\r\n      }\r\n    ]\r\n  },\r\n  resolve: {\r\n    extensions: ['.ts', '.js', '.vue', '.json'],\r\n    alias: {\r\n      'vue$': 'vue/dist/vue.esm.js'\r\n    }\r\n  },\r\n  devServer: {\r\n    historyApiFallback: true,\r\n    noInfo: true\r\n  },\r\n  performance: {\r\n    hints: false\r\n  },\r\n  devtool: '#eval-source-map',\r\n  plugins: [\r\n    // make sure to include the plugin for the magic\r\n    new VueLoaderPlugin()\r\n  ]\r\n}\r\n\r\nif (process.env.NODE_ENV === 'production') {\r\n  module.exports.devtool = '#source-map'\r\n  // http://vue-loader.vuejs.org/en/workflow/production.html\r\n  module.exports.plugins = (module.exports.plugins || []).concat([\r\n    new webpack.DefinePlugin({\r\n      'process.env': {\r\n        NODE_ENV: '\"production\"'\r\n      }\r\n    }),\r\n    new webpack.optimize.UglifyJsPlugin({\r\n      sourceMap: true,\r\n      compress: {\r\n        warnings: false\r\n      }\r\n    }),\r\n    new webpack.LoaderOptionsPlugin({\r\n      minimize: true\r\n    })\r\n  ])\r\n}\r\n```\r\n\r\n# Add a build script\r\n\r\nOpen up your `package.json` and add a script named `build` to run Webpack.\r\nYour `\"scripts\"` field should look something like this:\r\n\r\n```json\r\n\"scripts\": {\r\n    \"build\": \"webpack\",\r\n    \"test\": \"echo \\\"Error: no test specified\\\" \u0026\u0026 exit 1\"\r\n  },\r\n```\r\n\r\nOnce we add an entry point, we'll be able to build by running\r\n\r\n```sh\r\nnpm run build\r\n```\r\n\r\nand have builds get triggered on changes by running\r\n\r\n```sh\r\nnpm run build -- --watch\r\n```\r\n\r\n# Create a basic project\r\n\r\nLet's create the most bare-bones Vue \u0026 TypeScript example that we can try out.\r\nFirst, create the file `./src/index.ts`:\r\n\r\n```ts\r\n// src/index.ts\r\n\r\nimport Vue from \"vue\";\r\n\r\nlet v = new Vue({\r\n    el: \"#app\",\r\n    template: `\r\n    \u003cdiv\u003e\r\n        \u003cdiv\u003eHello {{name}}!\u003c/div\u003e\r\n        Name: \u003cinput v-model=\"name\" type=\"text\"\u003e\r\n    \u003c/div\u003e`,\r\n    data: {\r\n        name: \"World\"\r\n    }\r\n});\r\n\r\n```\r\n\r\nLet's check to see if everything is wired up correctly.\r\nCreate an `index.html` with the following content at your root:\r\n\r\n```html\r\n\u003c!doctype html\u003e\r\n\u003chtml\u003e\r\n\u003chead\u003e\u003c/head\u003e\r\n\r\n\u003cbody\u003e\r\n    \u003cdiv id=\"app\"\u003e\u003c/div\u003e\r\n\u003c/body\u003e\r\n\u003cscript src=\"./dist/build.js\"\u003e\u003c/script\u003e\r\n\r\n\u003c/html\u003e\r\n```\r\n\r\nNow run `npm run build` and open up your `index.html` file in a browser.\r\n\r\nYou should see some text that says `Hello World!`.\r\nBelow that, you'll see a textbox.\r\nIf you change the content of the textbox, you'll notice how the text is synchronized between the two.\r\n\r\nCongrats!\r\nYou've gotten TypeScript and Vue fully hooked up!\r\n\r\n# Adding a component\r\n\r\nAs you've just seen, Vue has a very simple interface for when you need to accomplish simple tasks.\r\nWhen our page only needed to communicate a bit of data between two elements, it took very little code.\r\n\r\nFor more complex tasks, Vue is flexible in that it supports breaking your application into *components*.\r\n[Components](https://vuejs.org/v2/guide/components.html) are useful for separating the concerns of how entities are displayed to the user.\r\n[Read up more on components from Vue's documentation.](https://vuejs.org/v2/guide/components.html)\r\n\r\nA Vue component can be declared in the following manner:\r\n\r\n```ts\r\n// src/components/Hello.ts\r\n\r\nimport Vue from \"vue\";\r\n\r\nexport default Vue.extend({\r\n    template: `\r\n        \u003cdiv\u003e\r\n            \u003cdiv\u003eHello {{name}}{{exclamationMarks}}\u003c/div\u003e\r\n            \u003cbutton @click=\"decrement\"\u003e-\u003c/button\u003e\r\n            \u003cbutton @click=\"increment\"\u003e+\u003c/button\u003e\r\n        \u003c/div\u003e\r\n    `,\r\n    props: ['name', 'initialEnthusiasm'],\r\n    data() {\r\n        return {\r\n            enthusiasm: this.initialEnthusiasm,\r\n        }\r\n    },\r\n    methods: {\r\n        increment() { this.enthusiasm++; },\r\n        decrement() {\r\n            if (this.enthusiasm \u003e 1) {\r\n                this.enthusiasm--;\r\n            }\r\n        },\r\n    },\r\n    computed: {\r\n        exclamationMarks(): string {\r\n            return Array(this.enthusiasm + 1).join('!');\r\n        }\r\n    }\r\n});\r\n```\r\n\r\nThis component has two buttons and some text.\r\nWhen rendered, it takes an initial `name` and an `initialEnthusiasm` which is the number of exclamation marks we want to display.\r\nWhen we hit the `+` button, it adds an exclamation mark to the end of the text.\r\nLikewise, when we hit the `-` button, it removes an exclamation mark unless we're down to just one.\r\n\r\nOur root Vue instance can consume it as follows:\r\n\r\n```ts\r\n// src/index.ts\r\n\r\nimport Vue from \"vue\";\r\nimport HelloComponent from \"./components/Hello\";\r\n\r\nlet v = new Vue({\r\n    el: \"#app\",\r\n    template: `\r\n    \u003cdiv\u003e\r\n        Name: \u003cinput v-model=\"name\" type=\"text\"\u003e\r\n        \u003chello-component :name=\"name\" :initialEnthusiasm=\"5\" /\u003e\r\n    \u003c/div\u003e\r\n    `,\r\n    data: { name: \"World\" },\r\n    components: {\r\n        HelloComponent\r\n    }\r\n});\r\n```\r\n\r\nHowever, we'll note that it is fairly popular to use [Vue's *single file components*](https://vuejs.org/v2/guide/single-file-components.html).\r\nLet's try writing the above as an SFC.\r\n\r\n# Single File Components\r\n\r\nWhen using Webpack or Browserify, Vue has plugins like [vue-loader](https://github.com/vuejs/vue-loader) and [vueify](https://www.npmjs.com/package/vueify) which allow you to author your components in HTML-like files.\r\nThese files, which end in a `.vue` extension, are single file components.\r\n\r\nThere are a few things that need to be put in place to use `.vue` files with TypeScript, but luckily we're already halfway there.\r\nWe already installed vue-loader earlier when we got our dev dependencies.\r\nWe also specified the `appendTsSuffixTo: [/\\.vue$/],` option to ts-loader in our `webpack.config.js` file, which allows TypeScript to process the code extracted from a single file component.\r\n\r\nOne extra thing we'll have to do is tell TypeScript what `.vue` files will look like when they're imported.\r\nWe'll do this with a `vue-shims.d.ts` file:\r\n\r\n```ts\r\n// src/vue-shims.d.ts\r\n\r\ndeclare module \"*.vue\" {\r\n    import Vue from \"vue\";\r\n    export default Vue;\r\n}\r\n```\r\n\r\nWe don't need to import this file anywhere.\r\nIt's automatically included by TypeScript, and it tells it that anything imported that ends in `.vue` has the same shape of the Vue constructor itself.\r\n\r\nWhat's left?\r\nThe editing experience!\r\nOne of the best features TypeScript gives us is its editor support.\r\nTo leverage that within `.vue` files, we recommend using [Visual Studio Code](https://code.visualstudio.com/) with the [Vetur](https://marketplace.visualstudio.com/items?itemName=octref.vetur) plugin for Vue.\r\n\r\nNow, let's write an SFC!\r\n\r\n```html\r\n\u003c!-- src/components/Hello.vue --\u003e\r\n\r\n\u003ctemplate\u003e\r\n    \u003cdiv\u003e\r\n        \u003cdiv class=\"greeting\"\u003eHello {{name}}{{exclamationMarks}}\u003c/div\u003e\r\n        \u003cbutton @click=\"decrement\"\u003e-\u003c/button\u003e\r\n        \u003cbutton @click=\"increment\"\u003e+\u003c/button\u003e\r\n    \u003c/div\u003e\r\n\u003c/template\u003e\r\n\r\n\u003cscript lang=\"ts\"\u003e\r\nimport Vue from \"vue\";\r\n\r\nexport default Vue.extend({\r\n    props: ['name', 'initialEnthusiasm'],\r\n    data() {\r\n        return {\r\n            enthusiasm: this.initialEnthusiasm,\r\n        }\r\n    },\r\n    methods: {\r\n        increment() { this.enthusiasm++; },\r\n        decrement() {\r\n            if (this.enthusiasm \u003e 1) {\r\n                this.enthusiasm--;\r\n            }\r\n        },\r\n    },\r\n    computed: {\r\n        exclamationMarks(): string {\r\n            return Array(this.enthusiasm + 1).join('!');\r\n        }\r\n    }\r\n});\r\n\u003c/script\u003e\r\n\r\n\u003cstyle\u003e\r\n.greeting {\r\n    font-size: 20px;\r\n}\r\n\u003c/style\u003e\r\n```\r\n\r\nand let's import it for our root instance:\r\n\r\n```ts\r\n// src/index.ts\r\n\r\nimport Vue from \"vue\";\r\nimport HelloComponent from \"./components/Hello.vue\";\r\n\r\nlet v = new Vue({\r\n    el: \"#app\",\r\n    template: `\r\n    \u003cdiv\u003e\r\n        Name: \u003cinput v-model=\"name\" type=\"text\"\u003e\r\n        \u003chello-component :name=\"name\" :initialEnthusiasm=\"5\" /\u003e\r\n    \u003c/div\u003e\r\n    `,\r\n    data: { name: \"World\" },\r\n    components: {\r\n        HelloComponent\r\n    }\r\n});\r\n```\r\n\r\nNotice a few things about our single-file component:\r\n\r\n* We had to write `\u003cscript lang=\"ts\"\u003e` to get it working with TypeScript.\r\n* We had to import the component with the `.vue` extension in `index.ts`.\r\n* We were able to write CSS isolated to our components in a `\u003cstyle\u003e` tag, which we couldn't do in our `.ts` components.\r\n* We default-exported a call to `Vue.extend` (rather than the options bag itself).\r\n  If you don't write `Vue.extend`, Vetur will make it look like things are working correctly, but you'll get an error when you build your project.\r\n\r\nTry running `npm run build` and open up `index.html` to see the result!\r\n\r\n# Using decorators to define a component\r\n\r\nComponents can also be defined using [decorators](https://www.typescriptlang.org/docs/handbook/decorators.html).\r\nWith the help of two additional packages, ([vue-class-component](https://github.com/vuejs/vue-class-component) and [vue-property-decorator](https://github.com/kaorun343/vue-property-decorator)), our components can be rewritten in the following manner:\r\n\r\n```ts\r\nimport { Vue, Component, Prop } from \"vue-property-decorator\";\r\n\r\n@Component\r\nexport default class HelloDecorator extends Vue {\r\n    @Prop() name!: string;\r\n    @Prop() initialEnthusiasm!: number;\r\n\r\n    enthusiasm = this.initialEnthusiasm;\r\n\r\n    increment() {\r\n        this.enthusiasm++;\r\n    }\r\n    decrement() {\r\n        if (this.enthusiasm \u003e 1) {\r\n            this.enthusiasm--;\r\n        }\r\n    }\r\n\r\n    get exclamationMarks(): string {\r\n        return Array(this.enthusiasm + 1).join('!');\r\n    }\r\n}\r\n```\r\n\r\nInstead of using `Vue.extend` to define our component, we create a class extending `Vue` and decorate it using the `@Component` decorator from the `vue-class-component` package (which was re-exported from the `vue-property-decorator` package).\r\n\r\nProperties are defined by prefixing instance variables with the `@Prop()` decorator from the `vue-property-decorator` package.\r\nBecause the `--strictPropertyInitialization` option is on, we need to tell TypeScript that Vue will initialize our properties by appending a `!` to them.\r\nThis tells TypeScript \"hey, relax, someone else is going to assign this property a value.\"\r\n\r\nRegular instance variables, such as `enthusiasm` in our example, are automatically made available for data binding to the template, just as if they had been defined in the `data` field.\r\nNote that all variables must be set to a value other than `undefined` for the binding to work.\r\n\r\nSimilarly, methods such as `increment` are treated as if they had been written in the `methods` field, and are automatically made available for the template.\r\n\r\nFinally, computed properties like `exclamationMarks` are simply written as `get` accessors.\r\n\r\n# What next?\r\n\r\nYou can [try out this application by cloning it from GitHub](https://github.com/DanielRosenwasser/typescript-vue-tutorial).\r\n\r\nOnce you feel like you've got a handle on that, you can try out a sample [TodoMVC-style app written in TypeScript and Vue](https://github.com/DanielRosenwasser/typescript-vue-todomvc).\r\nThis TodoMVC-style sample features routing through [vue-router](https://github.com/vuejs/vue-router) so that your application can show different views depending on the current URL.\r\n\r\nYou may also want to look into [Vuex](https://github.com/vuejs/vuex) if you're looking for [Redux](http://redux.js.org/)-style state management.\r\n","funding_links":[],"categories":["Web Frontend","JavaScript","TypeScript Starter/Boilerplate"],"sub_categories":["英文资源"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMicrosoft%2FTypeScript-Vue-Starter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FMicrosoft%2FTypeScript-Vue-Starter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FMicrosoft%2FTypeScript-Vue-Starter/lists"}