├── .gitattributes ├── .gitignore ├── README.md ├── babel.config.js ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── img │ └── icons │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon-120x120.png │ │ ├── apple-touch-icon-152x152.png │ │ ├── apple-touch-icon-180x180.png │ │ ├── apple-touch-icon-60x60.png │ │ ├── apple-touch-icon-76x76.png │ │ ├── apple-touch-icon.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── msapplication-icon-144x144.png │ │ ├── mstile-150x150.png │ │ └── safari-pinned-tab.svg ├── index.html ├── manifest.json └── robots.txt ├── src ├── App.vue ├── assets │ └── logo.png ├── components │ ├── HelloWorld.vue │ └── Sports.vue ├── main.ts ├── registerServiceWorker.ts ├── router.ts ├── shims-tsx.d.ts ├── shims-vue.d.ts ├── store │ ├── actions.ts │ ├── getters.ts │ ├── index.ts │ ├── mutations.ts │ ├── state.ts │ └── types.ts └── views │ ├── About.vue │ ├── Home.vue │ └── News.vue └── tsconfig.json /.gitattributes: -------------------------------------------------------------------------------- 1 | # *.ts linguist-language=TypeScript+Vue 2 | # *.vue linguist-language=TypeScript+Vue 3 | # *.js linguist-language=TypeScript+Vue 4 | # *.css linguist-language=TypeScript+Vue 5 | # *.html linguist-language=TypeScript+Vue -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vue+TypeScript从零开始 2 | typescript来编写Vue的好处不言而喻了,我们也静静的期待vue3版本的到来,会有更好的ts支持 3 | 4 | ## 脚手架工具与开发工具和插件 5 | Vue CLI 3 可以使用 TypeScript 生成新工程。创建方式: 6 | ``` 7 | # 1. 如果没有安装 Vue CLI 就先安装 8 | npm install --global @vue/cli 9 | 10 | # 2. 创建一个新工程,并选择 "Manually select features (手动选择特性)" 选项 11 | vue create my-project-name 12 | ``` 13 | 14 | 要使用 TypeScript 开发 Vue 应用程序,我们强烈建议您使用 Visual Studio Code,它为 TypeScript 提供了极好的“开箱即用”支持。如果你正在使用单文件组件 (SFC), 可以安装提供 SFC 支持以及其他更多实用功能的 Vetur 插件。 15 | 16 | ## 先给出参考站点: 17 | > vuex-class的参考:https://github.com/ktsn/vuex-class/ 18 | 19 | > vue-class-component装饰器的参考:https://github.com/kaorun343/vue-property-decorator 20 | 21 | ## 改变写法部分 22 | 下面介绍每个点的使用 23 | 24 | ### 组件引入 25 | ``` 26 | 38 | 39 | ``` 40 | 41 | ### data 42 | ``` 43 | 54 | 55 | ``` 56 | 57 | ### props 58 | ``` 59 | 67 | ``` 68 | 69 | ### 事件 70 | ``` 71 | 81 | ``` 82 | 83 | ### 生命周期 84 | 此处无变化 85 | 86 | ### 计算属性 87 | ``` 88 | 97 | ``` 98 | 99 | 100 | ## 集成Axios 101 | 这里其实和之前没变化,但是在挂载的时候会有变化 102 | ``` 103 | import axios from "axios" 104 | import Vueaxios from 'vue-axios' 105 | // axios ts中不支持挂在到原型,可以这样来实现 106 | Vue.use(Vueaxios, axios) 107 | ``` 108 | 109 | ## 集成Element-UI 110 | 此处无变化 111 | 112 | ## 集成VueX 113 | 首先在`src/`根目录下创建`/src/store`文件夹,并且创建对应的文件如下 114 | > types.ts 115 | ``` 116 | export interface RootStateTypes { 117 | city: string; 118 | } 119 | ``` 120 | 121 | > actions.ts 122 | ``` 123 | import state from './state' 124 | import { RootStateTypes } from './types' 125 | import { ActionTree } from 'vuex' 126 | 127 | const actions: ActionTree = { 128 | SET_CITY({ commit, state: RootStateTypes}, data: string) { 129 | commit('SET_CITY', data); 130 | } 131 | } 132 | 133 | export default actions 134 | ``` 135 | 136 | 137 | > mutations.ts 138 | ``` 139 | import state from './state' 140 | import { RootStateTypes } from './types' 141 | import { MutationTree } from 'vuex' 142 | 143 | const mutations: MutationTree = { 144 | SET_CITY(state: RootStateTypes, data: string) { 145 | state.city = data; 146 | } 147 | } 148 | 149 | export default mutations 150 | ``` 151 | 152 | > state.ts 153 | ``` 154 | import { RootStateTypes } from './types' 155 | const state: RootStateTypes = { 156 | city: '北京' 157 | } 158 | export default state 159 | ``` 160 | 161 | > getters.ts 162 | ``` 163 | import state from './state' 164 | import { RootStateTypes } from './types' 165 | import { GetterTree } from 'vuex' 166 | 167 | const getters: GetterTree = { 168 | city: (state: RootStateTypes) => state.city 169 | } 170 | 171 | export default getters 172 | ``` 173 | 174 | > index.ts 175 | ``` 176 | import Vue from 'vue' 177 | import Vuex, { Store } from 'vuex' 178 | import actions from './actions' 179 | import mutations from './mutations' 180 | import state from './state' 181 | import getters from './getters' 182 | 183 | Vue.use(Vuex) 184 | 185 | const store: Store = new Vuex.Store({ 186 | actions, 187 | mutations, 188 | getters, 189 | state, 190 | modules: { 191 | //添加自定义模块 192 | } 193 | }) 194 | 195 | export default store 196 | ``` 197 | 198 | 使用的时候如下: 199 | > News.vue 200 | ``` 201 | import { State, Getter, Mutation, Action } from 'vuex-class' 202 | // vuex 203 | @Getter city:any; 204 | // @Mutation SET_CITY:any; 205 | @Action SET_CITY:any; 206 | ``` -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-ts", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build" 8 | }, 9 | "dependencies": { 10 | "axios": "^0.18.0", 11 | "core-js": "^2.6.5", 12 | "element-ui": "^2.7.2", 13 | "register-service-worker": "^1.6.2", 14 | "vue": "^2.6.10", 15 | "vue-class-component": "^7.0.2", 16 | "vue-property-decorator": "^8.1.0", 17 | "vue-router": "^3.0.3", 18 | "vuex": "^3.1.0", 19 | "vuex-class": "^0.3.2" 20 | }, 21 | "devDependencies": { 22 | "@vue/cli-plugin-babel": "^3.6.0", 23 | "@vue/cli-plugin-pwa": "^3.6.0", 24 | "@vue/cli-plugin-typescript": "^3.6.0", 25 | "@vue/cli-service": "^3.6.0", 26 | "less": "^3.0.4", 27 | "less-loader": "^4.1.0", 28 | "typescript": "^3.4.3", 29 | "vue-axios": "^2.1.4", 30 | "vue-template-compiler": "^2.5.21" 31 | }, 32 | "postcss": { 33 | "plugins": { 34 | "autoprefixer": {} 35 | } 36 | }, 37 | "browserslist": [ 38 | "> 1%", 39 | "last 2 versions", 40 | "not ie <= 8" 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickiwen/vue-typescript/9a1d6d9a694d49c3d033e61429b8b5698e5b98f8/public/favicon.ico -------------------------------------------------------------------------------- /public/img/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickiwen/vue-typescript/9a1d6d9a694d49c3d033e61429b8b5698e5b98f8/public/img/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/img/icons/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickiwen/vue-typescript/9a1d6d9a694d49c3d033e61429b8b5698e5b98f8/public/img/icons/android-chrome-512x512.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickiwen/vue-typescript/9a1d6d9a694d49c3d033e61429b8b5698e5b98f8/public/img/icons/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickiwen/vue-typescript/9a1d6d9a694d49c3d033e61429b8b5698e5b98f8/public/img/icons/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickiwen/vue-typescript/9a1d6d9a694d49c3d033e61429b8b5698e5b98f8/public/img/icons/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickiwen/vue-typescript/9a1d6d9a694d49c3d033e61429b8b5698e5b98f8/public/img/icons/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickiwen/vue-typescript/9a1d6d9a694d49c3d033e61429b8b5698e5b98f8/public/img/icons/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /public/img/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickiwen/vue-typescript/9a1d6d9a694d49c3d033e61429b8b5698e5b98f8/public/img/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /public/img/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickiwen/vue-typescript/9a1d6d9a694d49c3d033e61429b8b5698e5b98f8/public/img/icons/favicon-16x16.png -------------------------------------------------------------------------------- /public/img/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickiwen/vue-typescript/9a1d6d9a694d49c3d033e61429b8b5698e5b98f8/public/img/icons/favicon-32x32.png -------------------------------------------------------------------------------- /public/img/icons/msapplication-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickiwen/vue-typescript/9a1d6d9a694d49c3d033e61429b8b5698e5b98f8/public/img/icons/msapplication-icon-144x144.png -------------------------------------------------------------------------------- /public/img/icons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickiwen/vue-typescript/9a1d6d9a694d49c3d033e61429b8b5698e5b98f8/public/img/icons/mstile-150x150.png -------------------------------------------------------------------------------- /public/img/icons/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by potrace 1.11, written by Peter Selinger 2001-2013 9 | 10 | 12 | 148 | 149 | 150 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | vue-ts 9 | 10 | 11 | 14 |
15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-ts", 3 | "short_name": "vue-ts", 4 | "icons": [ 5 | { 6 | "src": "./img/icons/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "./img/icons/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "start_url": "./index.html", 17 | "display": "standalone", 18 | "background_color": "#000000", 19 | "theme_color": "#4DBA87" 20 | } 21 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 31 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nickiwen/vue-typescript/9a1d6d9a694d49c3d033e61429b8b5698e5b98f8/src/assets/logo.png -------------------------------------------------------------------------------- /src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | 17 | 18 | 34 | -------------------------------------------------------------------------------- /src/components/Sports.vue: -------------------------------------------------------------------------------- 1 | 6 | 17 | 20 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import axios from "axios" 5 | import Vueaxios from 'vue-axios' 6 | import ElementUI from 'element-ui'; 7 | import store from './store/index' 8 | import 'element-ui/lib/theme-chalk/index.css'; 9 | import './registerServiceWorker' 10 | 11 | // axios ts中不支持挂在到原型,可以这样来实现 12 | Vue.use(Vueaxios, axios) 13 | Vue.use(ElementUI) 14 | Vue.config.productionTip = false 15 | 16 | new Vue({ 17 | router, 18 | store, 19 | render: h => h(App) 20 | }).$mount('#app') 21 | -------------------------------------------------------------------------------- /src/registerServiceWorker.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | 3 | import { register } from 'register-service-worker' 4 | 5 | if (process.env.NODE_ENV === 'production') { 6 | register(`${process.env.BASE_URL}service-worker.js`, { 7 | ready () { 8 | console.log( 9 | 'App is being served from cache by a service worker.\n' + 10 | 'For more details, visit https://goo.gl/AFskqB' 11 | ) 12 | }, 13 | registered () { 14 | console.log('Service worker has been registered.') 15 | }, 16 | cached () { 17 | console.log('Content has been cached for offline use.') 18 | }, 19 | updatefound () { 20 | console.log('New content is downloading.') 21 | }, 22 | updated () { 23 | console.log('New content is available; please refresh.') 24 | }, 25 | offline () { 26 | console.log('No internet connection found. App is running in offline mode.') 27 | }, 28 | error (error) { 29 | console.error('Error during service worker registration:', error) 30 | } 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /src/router.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Home from './views/Home.vue' 4 | import News from '@/views/News.vue' 5 | 6 | Vue.use(Router) 7 | 8 | export default new Router({ 9 | mode: 'history', 10 | base: process.env.BASE_URL, 11 | routes: [ 12 | { 13 | path: '/', 14 | name: 'home', 15 | component: Home 16 | }, 17 | { 18 | path: '/about', 19 | name: 'about', 20 | // route level code-splitting 21 | // this generates a separate chunk (about.[hash].js) for this route 22 | // which is lazy-loaded when the route is visited. 23 | component: () => import(/* webpackChunkName: "about" */ './views/About.vue') 24 | }, 25 | { 26 | path:"/news", 27 | name:"news", 28 | component:News 29 | } 30 | ] 31 | }) 32 | -------------------------------------------------------------------------------- /src/shims-tsx.d.ts: -------------------------------------------------------------------------------- 1 | import Vue, { VNode } from 'vue' 2 | 3 | declare global { 4 | namespace JSX { 5 | // tslint:disable no-empty-interface 6 | interface Element extends VNode {} 7 | // tslint:disable no-empty-interface 8 | interface ElementClass extends Vue {} 9 | interface IntrinsicElements { 10 | [elem: string]: any 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import Vue from 'vue' 3 | export default Vue 4 | } 5 | -------------------------------------------------------------------------------- /src/store/actions.ts: -------------------------------------------------------------------------------- 1 | import state from './state' 2 | import { RootStateTypes } from './types' 3 | import { ActionTree } from 'vuex' 4 | 5 | const actions: ActionTree = { 6 | SET_CITY({ commit, state: RootStateTypes}, data: string) { 7 | commit('SET_CITY', data); 8 | } 9 | } 10 | 11 | export default actions -------------------------------------------------------------------------------- /src/store/getters.ts: -------------------------------------------------------------------------------- 1 | import state from './state' 2 | import { RootStateTypes } from './types' 3 | import { GetterTree } from 'vuex' 4 | 5 | const getters: GetterTree = { 6 | city: (state: RootStateTypes) => state.city 7 | } 8 | 9 | export default getters -------------------------------------------------------------------------------- /src/store/index.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex, { Store } from 'vuex' 3 | import actions from './actions' 4 | import mutations from './mutations' 5 | import state from './state' 6 | import getters from './getters' 7 | 8 | Vue.use(Vuex) 9 | 10 | const store: Store = new Vuex.Store({ 11 | actions, 12 | mutations, 13 | getters, 14 | state, 15 | modules: { 16 | //添加自定义模块 17 | } 18 | }) 19 | 20 | export default store -------------------------------------------------------------------------------- /src/store/mutations.ts: -------------------------------------------------------------------------------- 1 | import state from './state' 2 | import { RootStateTypes } from './types' 3 | import { MutationTree } from 'vuex' 4 | 5 | const mutations: MutationTree = { 6 | SET_CITY(state: RootStateTypes, data: string) { 7 | state.city = data; 8 | } 9 | } 10 | 11 | export default mutations -------------------------------------------------------------------------------- /src/store/state.ts: -------------------------------------------------------------------------------- 1 | import { RootStateTypes } from './types' 2 | const state: RootStateTypes = { 3 | city: '北京' 4 | } 5 | 6 | export default state -------------------------------------------------------------------------------- /src/store/types.ts: -------------------------------------------------------------------------------- 1 | export interface RootStateTypes { 2 | city: string; 3 | } -------------------------------------------------------------------------------- /src/views/About.vue: -------------------------------------------------------------------------------- 1 | 6 | 16 | -------------------------------------------------------------------------------- /src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 19 | -------------------------------------------------------------------------------- /src/views/News.vue: -------------------------------------------------------------------------------- 1 | 26 | 79 | 81 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "experimentalDecorators": true, 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "sourceMap": true, 13 | "baseUrl": ".", 14 | "types": [ 15 | "webpack-env" 16 | ], 17 | "paths": { 18 | "@/*": [ 19 | "src/*" 20 | ] 21 | }, 22 | "lib": [ 23 | "esnext", 24 | "dom", 25 | "dom.iterable", 26 | "scripthost" 27 | ] 28 | }, 29 | "include": [ 30 | "src/**/*.ts", 31 | "src/**/*.tsx", 32 | "src/**/*.vue", 33 | "tests/**/*.ts", 34 | "tests/**/*.tsx" 35 | ], 36 | "exclude": [ 37 | "node_modules" 38 | ] 39 | } 40 | --------------------------------------------------------------------------------