安装 Vue-cli 和 TypeScript
- 安装 typescript
$npm install -g typescript
- 安装 Vue 命令行工具:
$npm install -g vue-cli
,安装完成之后对应的命令行工具为vue
可以通过vue --help
来获得使用帮助。 - 我们通过
vue init
命令来初始化一个简单的项目。
vue init simple VueToDoDemo1
其中的simple
表示项目模块名称。其他自带的模板可以通过vue list
查看。按创建提示初始化好之后,进入项目目录。
可以发现vue
只是为我们创建了一个简单的index.html
文件。
简易集成 TypeScript
- 使用
$npm init
加入 npm 支持。 - 使用
npm
安装vue
库$npm install vue
- 使用
tsc
创建项目需要的tsconfig.json
文件。$tsc --init
- 将
vue-cli
生成的vue
代码使用 TypeScript 重写。
首先,创建一个app.ts
文件,如下:
由于 TS 是 JS 的超集,所以我只是简单的复制了原有的标签中的代码,
var app = new Vue({
el: '#app',
data: {
greeting: 'Welcome to your Vue.js app!',
docsURL: 'http://vuejs.org/guide/',
discordURL: 'https://chat.vuejs.org',
forumURL: 'http://forum.vuejs.org/'
},
methods: {
humanizeURL: function (url) {
return url
.replace(/^https?:\/\//, '')
.replace(/\/$/, '')
}
}
})
使用
tsc
编译 直接在项目根目录运行tsc
然后app.ts
会编译成app.js
当然因为我们本身就是 JS 代码,所以没什么变化 。将原来
index.html
中的script
元素使用。使用替换。
打包与模块
在上面的步骤中,会提示这样的错误:
app.ts(1,16): error TS2304: Cannot find name 'Vue'.
首先,我们使用 将 tsconfig.json
中的 "moduleResolution":"node"
配置取消注释。
然后在 app.ts 开头添加如下导入声明:
import Vue from "vue"
然后再运行 tsc
就没有这个错误了。
修改之后,再次刷新 chrome 提示错误:
Uncaught SyntaxError: Unexpected identifier
搜索了一下,建议给 script
标签加上 type="module"
属性。
修改之后提示跨域错误:
Access to Script at 'file:///Users/banxi/Workspace/VueToDoDemo1/app.js' from origin 'null' has been blocked by CORS policy: Invalid response. Origin 'null' is therefore not allowed access.
那我们不使用 file
协议来运行 index.html 文件。而是使用一个简单的 http 服务器,以避免上面的 CORS 问题。
可以使用 Python 来在当前目录当作 Web 的根目录。
python -m SimpleHTTPServer 8000
然后使用 http://localhost:8000/index.html
来访问。
同时将 index.html
头部的 vue
引用改成如下:
指定为引用 ES Module 兼容的版本。
但是还是报如下的错误:
vue.esm.js:370 Uncaught ReferenceError: process is not defined
at vue.esm.js:370
原因是 Vue 代码包含了对 Node 环境原始的 process.env.NODE_ENV
检查。所以还存在 Node 的process
对象引用。
从文档: https://cn.vuejs.org/v2/guide/installation.html 中是建议的话 esm
版本本来就是用来提供给 webpack
等打包工具用的。如果直接用 vue.js
版本的话则会提示如下的错误:
vue.js:9 Uncaught TypeError: Cannot set property 'Vue' of undefined
at vue.js:9
at vue.js:10
然后考虑到上面文档说,cdn的 Vue
就是‘UMD版本, 于是’改用
UMD包。编译出的
app.js` 如下:
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "vue"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var vue_1 = __importDefault(require("vue"));
var app = new vue_1.default({
el: '#app',
data: {
greeting: 'Welcome to your Vue.js app!',
docsURL: 'http://vuejs.org/guide/',
discordURL: 'https://chat.vuejs.org',
forumURL: 'http://forum.vuejs.org/'
},
methods: {
humanizeURL: function (url) {
return url
.replace(/^https?:\/\//, '')
.replace(/\/$/, '');
}
}
});
});
这样报错是没有报错了,但是感觉中间的代码没有执行。
然后尝试采用 amd 打包方式。编译后的代码如下:
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
define(["require", "exports", "vue"], function (require, exports, vue_1) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
vue_1 = __importDefault(vue_1);
var app = new vue_1.default({
el: '#app',
data: {
greeting: 'Welcome to your Vue.js app!',
docsURL: 'http://vuejs.org/guide/',
discordURL: 'https://chat.vuejs.org',
forumURL: 'http://forum.vuejs.org/'
},
methods: {
humanizeURL: function (url) {
return url
.replace(/^https?:\/\//, '')
.replace(/\/$/, '');
}
}
});
});
可以看到其实 UMD 的打包方式。其实通过了自己的方式来兼容了 amd
的打包方式。
于是在 index.html
头部先引入 require.js
然后没有报错了。但是还是觉得代码没有执行的感觉。
然后继续按 require.js
的模块定义及加载方式。来使用。
这里面说明了 require.js
使用上的两个特点。
1)CDN 资源可以通过 require.config
配置后使用。注意配置时路径后面的 .js
不要写,因为会自动加上。
2)本地 JS 模块可以直接通过模块名称(即文件名称)
到此现在 TypeScript + RequireJs 打包结合,已经将此 Demo 初步完善了。
后面将增加 Vue Component 及其他加入 Webpack 打包的集成。