使用 TypeScript 和 AngularJS 的 SharePoint 应用






4.78/5 (9投票s)
如何使用 TypeScript 和 Angular Js 创建 SharePoint 应用。
TypeScript 是什么
- 它为 JavaScript 添加了静态类型和结构化(类、模块等)。
- 类型注解
- 静态类型检查
- 类型定义
- 编译时检查
- 开源
- Angular2 支持
强类型
TypeScript 定义了成员变量和函数参数的类型。在转换为 JavaScript 时,类型会被移除。这使得编译器能够在编译时捕获类型错误,并为 IDE 提供智能感知功能。
JavaScript | Typescript |
function test(a ,b )
{
return a*b;
}
alert(test('one','two'))
| function test(a:number,b:number):number
{
return a*b;
}
alert(test(10,20));
|
编译器
我们用 TypeScript 编写的代码会被编译成 JavaScript 和映射文件。映射文件用于将 JavaScript 和 TypeScript 文件行映射起来,以便调试 TypeScript。
编译:tsc test.ts -> test.js
在将 TypeScript 代码编译成 JavaScript 时,类型注解会被移除。
var a:number = 3; var a = 3;
var b:string = 'abc'; var b = 'abc';
DefinitelyTyped
DefinitelyTyped
以接口的形式为现有的许多 JavaScript 库添加了定义。
- 描述了外部库中定义的类型(d.ts)
- 仅用于开发目的,不部署
- 用于检查类型
替代方案
- Dart
- CoffeeScript
- ClojureScript
- Fay
模块 & 导出关键字
模块与 C# 中的 namespace
相同,用于避免名称冲突并获得 IIFE 的功能。
使用模块的 TypeScript
要使模块的内部方面在模块外部可访问,我们需要使用 export 关键字声明。由于 Angular 控制器会访问模型和服务,因此我们使用了 export
关键字。
使用 NuGet 包管理器创建一个 SharePoint 托管应用和必要的 TypeScript 定义文件。
验证项目属性中是否可用 TypeScript 选项
如果缺少 TypeScript 选项,请按照以下步骤操作
卸载项目
编辑项目并包含以下行
<PropertyGroup>
<TypeScriptSourceMap>true</TypeScriptSourceMap>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\
TypeScript\Microsoft.TypeScript.targets" />
保存并重新加载项目。
通过包管理器控制台包含 DefinitelyTyped。
Install-Package angularjs.TypeScript.DefinitelyTyped
Project.ts
module App.Model {
export class Project {
public Title: string;
public Id: number;
public Client: string;
}
}
ProjectService.ts
///<reference path="project.ts">
module App.Service {
export class ProjectService {
static $inject = ['$http'];
constructor(private $http: ng.IHttpService) {
}
public getProjects(): ng.IPromise<any> {
var url = App.Config.appWebUrl + "/_api/SP.AppContextSite(@target)" +
"/web/lists/getbytitle('Projects')/items?$select=Title,ID,Client&" +
"@target='" + App.Config.hostUrl + "'";
console.log(url);
return this.$http({
method: 'GET',
url: url,
headers: { "Accept": "application/json; odata=verbose" }
});
}
public addProject(project: App.Model.Project): any {
console.log($("#__REQUESTDIGEST").val());
var data = {
__metadata: { 'type': 'SP.Data.ProjectsListItem' },
Title: project.Title,
Client: project.Client
};
var url = App.Config.appWebUrl + "/_api/SP.AppContextSite(@target)" +
"/web/lists/getbytitle('Projects')/items?" +
"@target='" + App.Config.hostUrl + "'";
return this.$http({
url: url,
method: "POST",
headers: {
"Content-Type": "application/json;odata=verbose",
"Accept": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val()
},
data: data
});
}
}
}
$Inject
如果没有注入,程序在 Js 被压缩之前可以正常工作。压缩过程可能会更改参数的名称,从而导致 Angular 无法注入。
$inject
是 AngularJS 的一个特殊属性,用于确定需要在运行时注入哪些服务。它应该标记为 static
,并且是一个 string
数组。数组 string
的顺序和构造函数参数的顺序应该匹配。
ProjectCtrl.ts
///<reference path="projectservice.ts" />
module App.Controller {
export class ProjectCtrl {
public projects: Array<App.Model.Project>
public project: App.Model.Project;
static $inject = ['ProjectService'];
constructor(private projectService: App.Service.ProjectService) {
this.project = new App.Model.Project();
}
public getProjects(): void {
this.projectService.getProjects().then(data => {
this.projects = data.data.d.results;
console.log(this.projects);
}).catch(e => {
alert('Error' + e);
});
}
public addProject(): void {
this.projectService.addProject(this.project).then(data => {
this.getProjects();
this.project = new App.Model.Project();
}).catch(e => {
alert('Error' + e);
});
}
}
}
App.ts
///<reference path="../scripts/typings/angularjs/angular.d.ts" />
///<reference path="../scripts/typings/angular-ui-router/angular-ui-router.d.ts" />
///<reference path="project/projectctrl.ts" />
module App {
export class Config {
private static manageQueryStringParameter(paramToRetrieve: string): any {
var params =
document.URL.split("?")[1].split("&");
var strParams = "";
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params[i].split("=");
if (singleParam[0] == paramToRetrieve)
return singleParam[1];
}
}
public static appWebUrl: string;
public static hostUrl: string;
static $inject = ["$stateProvider", "$urlRouterProvider"];
public static loadConfig(): void {
Config.appWebUrl = decodeURIComponent(this.manageQueryStringParameter("SPAppWebUrl"));
Config.hostUrl = decodeURIComponent(this.manageQueryStringParameter("SPHostUrl"));
}
}
var main = angular.module('projectApp', ['ui.router']);
App.Config.loadConfig();
main.controller('ProjectCtrl', App.Controller.ProjectCtrl);
main.service('ProjectService', ['$http', '$q', App.Service.ProjectService]);
}
构建项目并合并 TS 文件。
构建并将 test.js 和 test.map 文件包含在项目中。
打开element.xml,删除 .ts 文件路径,并包含 test.js 和 test.map 文件。
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="App">
<File Path="App\test.js" Url="App/test.js" ReplaceContent="TRUE" />
<File Path="App\test.js.map" Url="App/test.js.map" ReplaceContent="TRUE" />
</Module>
</Elements>
<html>
<head>
<link rel="Stylesheet" type="text/css" href="../Content/App.css" />
<script src="../Scripts/jquery-1.9.1.js"></script>
<script src="../Scripts/angular.js"></script>
<script src="../Scripts/angular-ui-router.js"></script>
<script src="../App/test.js"></script>
</head>
<body>
<form runat="server">
</form>
<h1>Project </h1>
<div ng-app="projectApp">
<div ng-controller="ProjectCtrl as vm">
<div style="float: left; border: 1px solid gray;">
<table ng-init="vm.getProjects()">
<tr>
<td>SNO</td>
<td>Project</td>
<td>Client</td>
</tr>
<tr ng-repeat="project in vm.projects">
<td>{{$index+1}}</td>
<td>{{project.Title}}</td>
<td>{{project.Client}}</td>
</tr>
</table>
</div>
<div>
<table>
<tr>
<td>Project</td>
<td>
<input type="text" ng-model="vm.project.Title" /></td>
</tr>
<tr>
<td>Client</td>
<td>
<input type="text" ng-model="vm.project.Client" /></td>
</tr>
<tr>
<td colspan="2">
<button ng-click="vm.addProject()">Add Project</button></td>
</tr>
</table>
</div>
</div>
</div>
</body>
</html>