上一篇文章我们使用Teams Toolkit 来创建、运行 tab app。这篇文章我们深入来分析看一下tab app 的代码。
先打开代码目录,可以看到在 src 目录下有入口文件 index.tsx
,然后在 components
目录下有更多的一些 tsx 文件,tsx 是 typescript的一种扩展文件,主要用于 react 开发。
我们打开 index.tsx
,看一下代码。
import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";
import "./index.css";ReactDOM.render(<App />, document.getElementById("root"));
可以看到代码极其简单明了,就是一个 <App>
,那我们就打开 App.tsx
看看。
import { Provider, teamsTheme } from "@fluentui/react-northstar";
import Privacy from "./Privacy";
import TermsOfUse from "./TermsOfUse";
import Tab from "./Tab";
import TabConfig from "./TabConfig";
import { useTeams } from "msteams-react-base-component";.........export default function App() {const { theme } = useTeams({})[0];return (<Provider theme={theme || teamsTheme} styles=><Router><Route exact path="/"><Redirect to="/tab" /></Route><><Route exact path="/privacy" component={Privacy} /><Route exact path="/termsofuse" component={TermsOfUse} /><Route exact path="/tab" component={Tab} /><Route exact path="/config" component={TabConfig} /></></Router></Provider>);
}
App.tsx
也算简单,有几个地方需要我们注意的,第一个就是调用了 useTeams()
方法来获取当前的 teams 的theme,teams实际上有几个不同的theme,调用 “msteams-react-base-component” 的 useTeams()
就能够拿到当前的 theme,然后把 theme 设置给了 Provider,在 Router方面则一看就明白,配置了一些路径和对应的 component。
这些路径实际上在 manifest.json 里有用到。我们打开 /build/appPackage/manifest.local.json
文件,我们可以看到:
{..."developer": {"name": "Teams App, Inc.","websiteUrl": "https://localhost:53000","privacyUrl": "https://localhost:53000/index.html#/privacy","termsOfUseUrl": "https://localhost:53000/index.html#/termsofuse"},"configurableTabs": [{"configurationUrl": "https://localhost:53000/index.html#/config","canUpdateConfiguration": true,"scopes": ["team","groupchat"]}],"staticTabs": [{"entityId": "index","name": "Personal Tab","contentUrl": "https://localhost:53000/index.html#/tab","websiteUrl": "https://localhost:53000/index.html#/tab","scopes": ["personal"]}],....
}
Privacy.tsx
和 TermsOfUse.tsx
非常简单,我们不在展开,我们先来看一下 TabConfig.tsx
。简化后的内容如下:
import { app, pages } from "@microsoft/teams-js";class TabConfig extends React.Component {render() {app.initialize().then(() => {pages.config.registerOnSaveHandler((saveEvent) => {const baseUrl = `https://${window.location.hostname}:${window.location.port}`;pages.config.setConfig({suggestedDisplayName: "My Tab",entityId: "Test",contentUrl: baseUrl + "/index.html#/tab",websiteUrl: baseUrl + "/index.html#/tab",}).then(() => {saveEvent.notifySuccess();});});pages.config.setValidityState(true);});return (<div>...</div>);}
}
这个基本是 tab 配置页面的标准写法,调用 app.initialize()
方法,然后注册一个 “Save” buttton 的回调函数,在这个回调函数里,调用 pages.config.setConfig()
函数来告诉 Teams,我们新建的tab的配置,新建的tab 的url是什么。
注册完后,调用了 pages.config.setValidityState(true);
来告诉 Teams,我们的 config 页面已经配置好了,可以让用户来点击 Save 按钮了。这里面有点绕,但如果各位仔细看上面的代码,也不难理解。
我们再来整理一下这个流程:
app.initialize().then(() => {pages.config.registerOnSaveHandler((saveEvent) => { // 注册回调函数,当用户点击 Save 按钮时,这个方法会被触发const baseUrl = `https://${window.location.hostname}:${window.location.port}`;pages.config.setConfig({ // 告诉 Teams 新建的 tab 的具体情况,比如tab 名字和 urlsuggestedDisplayName: "My Tab",entityId: "Test",contentUrl: baseUrl + "/index.html#/tab",websiteUrl: baseUrl + "/index.html#/tab",}).then(() => {saveEvent.notifySuccess(); // 告诉 Teams,Save点击事件处理完毕});});pages.config.setValidityState(true); // 告诉 Teams可以允许用户点击 Save 按钮});return (<div>...</div> // 返回 config 页面的 html 内容);
*/index.html#/tab
对应到的是 Tab component,对于 Tab 具体页面里基本都是React的一些写法,我这里就不再展开讲 React 开发了,值得一提的是,我们应该尽量使用 fluentui
和 msteams-react-base-component
库,让使用 React 开发teams tab更加方便,并且风格和teams更加一致。