开始概念API和它的JavaScript SDK
概念是一个多功能的应用程序,用于组织各种内容,从笔记到日历和提醒。concept最近也推出了自己的服务API,在本文中,我们将使用这个API创建一个小接口,将concept连接到我们自己的数据库。
概念已经向世界发布了它的API开放测试.它有优秀的文档,它真的很容易访问,更重要的是,对于我们JavaScript开发者,它还提供了一个JavaScript SDK.
虽然阅读本文不需要任何相关知识(我将提供所有必需的步骤),但我们将处理前端和后端代码,因为其中涉及到一些Node.js和Express设置。
设置
我们的设置将分为两个部分。第一部分将介绍我们在使用concept软件和API时需要遵循的步骤。在第二部分中,我们将通过初始化文件夹、添加concept依赖项和创建初始值来获得代码index.js
编辑package.json
让一切正常运转。
要继续学习,您需要一个concept帐户(下文将详细介绍),以及一份最新的节点安装在您的机器上.一如既往,教程的代码可以在GitHub上找到.
如果您还没有一个概念帐户,请按以下步骤创建一个这个链接.它有一个非常慷慨的免费层,你不需要添加任何支付信息!
创建帐户并登录后,通过选择创建一个新页面添加页面给它起个名字。对于本教程,我们将选择表格
数据库。这将给我们一个空表,这正是我们想要的!
下一步是在我们的数据库
然后用一些模拟数据填充它们。在本教程中,我们只使用的名字
而且角色
字段,就好像我们在处理公司员工的数据库一样。
现在我们去文档的网站.你会看到我的集成链接在右上角。如果你点击它,你会被引导到一个显示“我的集成”的屏幕,当然,你的将是空的。
新闻创建新的集成,填写你的头衔,并确保选择你的头衔相关的工作空间
(它将被默认选择,但请确保这一点)。新闻提交你会被引导到一个新的页面内部集成令牌
(我们将在我们的代码中使用它)和两个选项框,用于您想要使用集成的地方。您不需要在此页上做任何事情,除了复制您的令牌
并按保存更改.
注:在撰写本文时,似乎没有办法删除积分,所以要明智地命名它们。
现在回到您的concept工作区。在新创建的数据库上,我们希望按下分享,然后邀请.然后可以选择新创建的集成。选择并按下邀请,您的concept设置就完成了。做得好!
代码设置
现在让我们编写一些代码。打开你的终端机,然后做mkdir notion-api-test
(这将创建一个名为notion-api-test
),然后进入你的文件夹cd notion-api-test
,做NPM init -y
(此命令将创建一个package.json
用一些基本的设置和可能是
自动标记一些提示的答案,这样你就不必为它们而烦恼了)。
就像我之前提到的,我们要用notion-sdk-js,为此,我们需要将它作为依赖项安装,因此我们将这样做NPM安装@notionhq/client
.
现在,打开你的notion-api-test
在代码编辑器上创建一个首字母index.js
在根
并编辑package.json脚本s
用以下内容替换现有内容:
“脚本”:{“开始”:“节点指数”},
我们再来创建一个.gitignore
文件和另一个叫做.env
.的.gitignore
允许您在里面放置不同的文件/文件夹名称,这意味着当您推送代码时,这些文件/文件夹将不会添加到您的repo。这很重要,因为我们集成的令牌
(还记得吗?)将在.env
文件,像这样:
NOTION_API_KEY=YOUR_TOKEN_HERE
这意味着在你的.gitignore
你应该在第一行加上这个:
.env
现在我们有一个.env
文件,我们还应该添加一个新的依赖项,dotenv,这样你就可以加载你的NOTION_API_KEY
变量。你可以这样做NPM安装dotenv
.
代码设置现在已经完成,您的文件夹应该如下所示。
从概念API中提取数据
现在无聊的部分结束了,让我们进入精彩的部分吧!我们的index.js
文件将是一个Node.js文件,下面的代码块显示了我们的起始代码以及每一行的具体功能!
//这将允许我们导入变量需要(“dotenv”).配置();//初始化一个concept客户端需要以下几行代码常量{客户端}=需要(“@notionhq /客户端”);//这一行使用我们的键来初始化概念客户端常量概念=新客户端({身份验证:过程.env.NOTION_API_KEY});
这里还需要一个额外的东西,即我们在concept工作区中创建的数据库的ID。这可以从浏览器的URL栏获得。它位于您的工作区名称(如果您有的话)和斜杠(myworkspace /
)和问号(?
).ID长度为32个字符,由数字和字母组成。
https://www.notion.so/myworkspace/a8aec43384f447ed84390e8e42c2e089?v=...|---------数据库ID --------|
出于安全考虑,您还应该将此ID粘贴到您的.env
文件,这样它看起来就像这样:
NOTION_API_KEY=YOUR_TOKEN_HERE NOTION_API_DATABASE=YOUR_DATABASE_ID_HERE
然后我们将它导入到我们的index.js
用这个:
常量databaseId=过程.env.NOTION_API_DATABASE;
现在,为了确保API正常工作,让我们创建一个函数来调用数据库。要做到这一点,我们将创建一个异步函数
:
常量getDatabase=异步()= >{常量响应=等待概念.数据库.查询({database_id:databaseId});控制台.日志(响应);};getDatabase();
如果你现在跑npm开始
在您的终端中,您应该看到一个log of an对象
与一个结果
属性,该属性具有数组。该数组包含数据库中的条目。要了解它们,我们可以做以下工作:
常量getDatabase=异步()= >{常量响应=等待概念.数据库.查询({database_id:databaseId});常量responseResults=响应.结果.地图((页面)= >{返回{id:页面.id,的名字:页面.属性.的名字.标题[0]?.plain_text,角色:页面.属性.角色.rich_text[0]?.plain_text,};});//这个console.log只是为了让你看到我们在这里得到了什么控制台.日志(responseResults);返回responseResults;};
上面的代码映射到我们的结果
(匹配数据库中的条目),我们将不同属性的路径映射到我们所选择的名称(在本例中,id
,的名字
而且角色
).注意对象路径是多么特定。我使用可选的链接说明数据库中的空白行,或这些字段中的一个或另一个未填写的行。
无论采用哪种方式,都可以随意使用不同的属性,并注意这是一个反复试验的问题,而且每个API的行为和组织信息都是不同的。这里重要的事情是仔细检查每个属性,直到我们得到我们想要的信息。
如果查看每个属性和使用console.log ()
不是你的事情,你总是可以使用邮差检查响应。不幸的是,这不在本教程的范围内,但您可以检查“如何掌握你的API工作流程与邮差发帖试试吧!
这里还有一个重要的注意事项:注意notion.databases.query
我们用过。如果你看概念API文档,你会看到我们在用POST |查询数据库
.我们可以用检索数据库
,但在这里,我想挑战您阅读文档,并尝试以不同的方式对列表进行排序!
在结束这部分之前,让我们改变一下getDatabase
函数,这样我们就可以正确地将它导入到我们将要创建的另一个文件中。它看起来应该如下所示:
出口.getDatabase=异步函数(){常量响应=等待概念.数据库.查询({database_id:databaseId});常量responseResults=响应.结果.地图((页面)= >{返回{id:页面.id,的名字:页面.属性.的名字.标题[0]?.plain_text,角色:页面.属性.角色.rich_text[0]?.plain_text,};});返回responseResults;};
设置快速服务器
完成前一个步骤后,现在可以成功检索结果。但是为了能够正确地使用它们,我们需要创建一个服务器,而最简单的方法是使用表达.我们从跑步开始NPM安装快讯
并在根目录下创建一个名为server.js
.
如果表达
迷惑你,别担心。我们将使用它来方便我们的工作,并为我们的应用程序创建一个快速的后端和服务器。如果没有它,我们将无法正确地检索数据,因为我们在代码中初始化了concept客户机。
在我们的server.js
文件,我们将从导入开始表达
,即代码所在的模块(index.js
),我们getDatabase
函数、端口号和变量来初始化我们的表达
功能:
常量表达=需要(“表达”);//我们的模块常量moduleToFetch=需要(”。/指数”);//我们的函数常量getDatabase=moduleToFetch.getDatabase;常量港口=8000;常量应用程序=表达();//当你执行' npm start '时,最后一个命令将在你的终端上记录一条消息应用程序.听(港口,控制台.日志(`服务器在$ {港口}`));
由于我们现在将代码导入到一个新文件中,server.js
,我们应该改变我们的观念开始
命令package.json
寻找服务器
,所以它应该是这样的:
“脚本”:{“开始”:“节点服务器”},
如果你现在跑npm开始
,你会看到服务器在8000上启动
消息,这意味着我们的设置正在按预期工作!做得好!
现在我们表达
App在工作,我们需要让数据库和它一起工作,我们可以这样做app.get ()
.这个方法需要一个路径(在我们的例子中这无关紧要)和一个回调函数(它将调用我们的getDatabase
函数):
应用程序.得到(“/用户”,异步(要求的事情,res)= >{常量用户=等待getDatabase();res.json(用户);});
上面的代码使用app.get
方法,在回调函数中我们从函数中获取结果我们使用. json ()
表示将请求解析为可读和可操作数据的中间件函数。(你可以在官方文档.)
这意味着我们现在成功地访问了我们的数据,并且我们已经创建了一个“获取”它的路由。作为最后一步,我们应该添加app.use (express.static(“公共”));
对我们的server.js
文件,这样最终的结果看起来就像这样:
常量表达=需要(“表达”);//我们的模块常量moduleToFetch=需要(”。/指数”);//我们的函数常量getDatabase=moduleToFetch.getDatabase;常量港口=8000;常量应用程序=表达();//我们刚刚添加的代码行应用程序.使用(表达.静态(“公共”));应用程序.得到(“/用户”,异步(要求的事情,res)= >{常量用户=等待getDatabase();res.json(用户);});应用程序.听(港口,控制台.日志(`服务器在$ {港口}`));
最后这段代码告诉我们的后端使用
我们将在其中创建前端代码的特定文件夹,即公共
文件夹中。在这里,我们将使用我们的HTML, CSS和JavaScript来访问它/用户
我们在后端创建的路由。让我们开始吧!
显示来自概念API的数据
我们首先在项目的根目录下创建一个名为公共
.这里是前端代码的位置。
HTML和CSS部分很简单,所以我将主要把代码留在这里,专注于JavaScript部分,因为这就是我们在这里的目的!
我们的HTML (/公共/ index . html
)会是这样的:
<!文档类型超文本标记语言><超文本标记语言朗="在"><头><元字符集="utf - 8"/><元http-equiv="X-UA-Compatible"内容="IE =边缘"/><元的名字="视窗"内容="宽度=设备宽度,初始= 1.0"/><标题>概念API测试标题><链接rel="样式表"href="style.css"/>头><身体><divid="横幅">概念API数据库测试div><divid="包装器"><divid="容器">div>div><脚本类型="模块"src="。/ main.js">脚本>身体>超文本标记语言>
我们的CSS (/公共/ style.css
)会是这样的:
身体,超文本标记语言{填充:0;保证金:0;高度:One hundred.vh;宽度:One hundred.大众;字体类型:天线,海维提卡,无衬线;位置:相对;}#横幅{高度:50px;显示:flex;justify-content:中心;对齐项目:中心;背景颜色:# ef4444;颜色:白色;粗细:大胆的;}#包装{显示:flex;justify-content:中心;对齐项目:中心;高度:calc(One hundred.vh-50px);}#容器{宽度:80大众;保证金:汽车;显示:网格;grid-template-columns:重复(auto-fit,极大极小(250px,1fr));grid-auto-rows:200px;差距:20.px;}.userContainer{显示:flex;flex-direction:列;justify-content:中心;对齐项目:中心;不必:rgba(149,157,165,0.2)0px8px24px;这个特性:10px;}
如果你现在跑npm开始
在您的项目中并访问http://localhost:8000,您应该会看到前端代码。
现在我们公共/ main.js
文件!第一步是向我们在后端创建的路由发出请求(/用户/
),这样我们就可以撷取资料库的资料:
常量getDataFromBackend=异步()= >{常量休息=等待获取(“http://localhost: 8000 /用户”);常量数据=等待休息.json();返回数据;};//注意,顶级await仅在现代浏览器中可用/ / https://caniuse.com/mdn-javascript_operators_await_top_level常量res=等待getDataFromBackend();控制台.日志(res);
当您记录这个函数的返回值时,您将在开发人员工具中看到我们以前只能在终端上看到的相同信息,这意味着我们现在可以在前端使用我们的数据!好工作!
现在让我们在我们的< div id = "容器" > < / div >
,这将是非常简单的。我们从a开始getElementById
来获取合适的元素,然后我们将创建一个运行的函数getDataFromBackend ()
将遍历我们的数据
数组和推这个内容到我们的HTML。以下是我的方法:
//添加数据到HTML常量addData=异步()= >{常量数据=等待getDataFromBackend();数据.forEach((价值)= >{常量div=文档.createElement(" div ");div.班级名册.添加(“userContainer”);div.innerHTML=`<h3>$ {价值.的名字}h3><p>$ {价值.角色}p>`;容器.附加(div);});};addData();
再一次,我们的数据
变量(在addData
函数)是相同的信息,我们可以看到log(对象数组),我们通过创建一个< div >
有一个班级userContainer
,里面有的名字
而且角色
对于数据库中的每个条目。
如果现在运行代码,应该会看到如下图所示的内容!
将数据写入概念数据库
对于我们的concept API实验来说,这将是一个很好的停止点,但是我们还可以做更多的事情!现在让我们添加方法添加到数据库的新条目创建页面
POST请求(可以找到在这里),这样我们就有了一个功能完整、工作正常的应用程序,它使用了几乎所有概念API的功能。
因此,我们在这里的想法是在我们的前端添加一个表单,当填写和提交时,将把新数据推送到我们的数据库,然后显示在我们的前端!
让我们从添加一个新函数开始index.js
被称为newEntryToDatabase
.考虑到文档,我们现在应该这样做Const response = await concept .pages.create()
,我们应该传递一个与我们正在处理的当前数据库匹配的对象。它也有两个参数,的名字
而且角色
,对于这个项目,它看起来像这样:
出口.newEntryToDatabase=异步函数(的名字,角色){常量响应=等待概念.页面.创建({父:{database_id:过程.env.NOTION_API_DATABASE,},属性:{的名字:{标题:[{文本:{内容:的名字,},},],},角色:{rich_text:[{文本:{内容:角色,},},],},},});返回响应;};
注意我们在这个物体上做了什么。我们基本上是在做和之前一样的事情getDatabase
与我们的responseResults
变量,通过遍历每个属性,直到找到我们实际想要使用的属性。这里,我们使用参数作为属性的值。如果这看起来很混乱,那绝对没问题;查看本节的链接文档以查看更多示例!
现在,跳到我们的server.js
,我们不要忘记导入我们的新函数withconst newEntryToDatabase = moduleToFetch.newEntryToDatabase;
在文件的顶部。我们还会做a帖子
请求使用app.post ()
.这里我们还需要一个路线(它将是/提交表单
),我们的回调函数应该得到的名字
而且角色
从请求(我们填写的表单字段)和调用newEntryToDatabase
通过这两个论证。然后我们用重定向到我们的基本路由来完成我们的函数,/
我们也结束了我们的请求。
我们的server.js
文件中还需要一些代码app.use ()
函数,也就是express.urlencoded
.这是Express的中间件,所以我们可以使用帖子
请求,因为我们实际上在发送数据:
常量表达=需要(“表达”);常量moduleToFetch=需要(”。/指数”);常量getDatabase=moduleToFetch.getDatabase;//导入函数常量newEntryToDatabase=moduleToFetch.newEntryToDatabase;常量港口=8000;常量应用程序=表达();应用程序.使用(表达.静态(“公共”));应用程序.使用(表达.urlencoded({扩展:真正的,}));应用程序.得到(“/用户”,异步(要求的事情,res)= >{常量用户=等待getDatabase();res.json(用户);});//我们新添加的代码应用程序.帖子(“/提交表单”,异步(要求的事情,res)= >{常量的名字=要求的事情.身体.的名字;常量角色=要求的事情.身体.角色;等待newEntryToDatabase(的名字,角色);res.重定向(“/”);res.结束();});应用程序.听(港口,控制台.日志(`服务器在$ {港口}`));
我们的后端现在已经完成了,我们应该继续我们的前端代码。在这一点上,你应该重新启动Express服务器这样它就能识别变化。
公平地说,前端代码中唯一需要的是< >形式
在你的HTML中方法=“发布”
而且action = " /提交表单”
.这基本上告诉我们的代码这应该是什么类型的表单,并将它链接到一个路由(/提交表单
),我们创建它来处理请求。
所以像下面这样的东西就足够了:
<形式方法="帖子"行动="/提交表单"><输入类型="文本"的名字="的名字"占位符="插入用户名"要求/><输入类型="文本"的名字="角色"占位符="插入用户角色"要求/><输入类型="提交"/>形式>
如果我们填写字段并提交表单并重新加载页面,我们将看到一个新的条目,如果我们进入concept工作区,我们将在那里看到条目。功能完备。做得好!
但是为了改进我们的界面,这里的想法是我们会有一个按钮
,当单击时,将打开一个模态形式
(也有可能关闭它而不填充它),所以这是我的HTML:
<!--的休息of the code above --><divid="包装器"><divid="容器">div>div><divid="addUserFormContainer"><按钮id="closeFormButton">关闭按钮><形式方法="帖子"行动="/提交表单"id="addUserForm"><h1id="formTitle">向数据库中添加一个新用户h1><输入类型="文本"的名字="的名字"占位符="插入用户名"类="inputField"要求/><输入类型="文本"的名字="角色"占位符="插入用户角色"类="inputField"要求/><输入类型="提交"id="submitFormInput"/>形式>div><按钮id="newUserButton">添加新用户按钮><脚本类型="模块"src="。/ main.js">脚本><!--的休息of the code below -->
下面是应该伴随它的CSS:
/*上面剩下的代码*/# newUserButton{位置:绝对;底:10px;正确的:10px;填充:10px20.px;背景颜色:# ef4444;颜色:白色;粗细:大胆的;边境:没有一个;这个特性:4px;}# addUserFormContainer{位置:绝对;前:0;左:0;高度:One hundred.vh;宽度:One hundred.大众;显示:没有一个;flex-direction:列;justify-content:中心;对齐项目:中心;背景:rgba(255,255,255,0.4);backdrop-filter:模糊(20.px);}# closeFormButton{位置:绝对;前:10px;正确的:10px;填充:10px20.px;背景颜色:黑色的;颜色:白色;粗细:大胆的;边境:没有一个;这个特性:4px;}# formTitle{margin-bottom:40px;}# addUserForm{填充:50pxOne hundred.px;宽度:300px;显示:flex;flex-direction:列;justify-content:中心;对齐项目:中心;背景:白色;不必:rgba(149,157,165,0.2)0px8px24px;}# addUserForm输入{宽度:One hundred.%;box-sizing:border-box;}.inputField{margin-bottom:20.px;填充:10px20.px;边境:1px固体# b3b3b3;这个特性:4px;}# submitFormInput{填充:10px20.px;margin-bottom:没有一个;背景颜色:# ef4444;颜色:白色;粗细:大胆的;边境:1px固体# ef4444;这个特性:4px;}
如果现在访问您的页面,您将只看到一个红色按钮,没有真正的实用程序,所以现在我们需要处理JavaScript。因此让我们进入我们的/公共/ main.js
文件!
这里,我们从抓取# newUserButton
,# closeFormButton
和# addUserFormContainer
:
常量容器=文档.getElementById(“容器”);//新变量常量openFormButton=文档.getElementById(“newUserButton”);常量closeFormButton=文档.getElementById(“closeFormButton”);常量addUserFormContainer=文档.getElementById(“addUserFormContainer”);
现在在我们的openFormButton
我们添加一个点击
事件监听器,它最终将为我们的addUserFormContainer
与显示:flex
:
openFormButton.addEventListener(“点击”,()= >{addUserFormContainer.风格.显示=“弯曲”;});
现在如果你点击添加新用户按钮,它将打开表单。
关闭我们的形式
莫代尔,我们只需要去掉这个flex
我们通过按closeFormButton
,所以它应该是这样的:
closeFormButton.addEventListener(“点击”,()= >{addUserFormContainer.风格.显示=“没有”;});
我们完成了!现在,当您在表单中输入名称和角色时,它们将被添加到您的concept数据库中,并将显示在应用程序的前端。
我们刚刚建立了一个功能齐全的网站,它可以获取数据库,处理数据,显示数据,还允许您添加数据!是不是很不可思议?
这里有一个简短的视频演示完成的结果。
更进一步
虽然这个演示展示了concept API的一些重要用途,但我们的应用程序仍有改进的空间。例如,建议实现一些错误处理,或者加载旋转器显示应用程序何时与concept通信(因此没有响应)。此外,不必总是查询API来检索数据,您可以很容易地将其转换为单页应用程序,只查询API一次,然后保持我们正在处理的数据处于状态。
如果您希望帮助实现这些内容,或者希望展示您的解决方案,为什么不呢去SitePoint论坛告必威西盟体育网页登录诉我们吧.
结论
在这个项目中,我们几乎探索了concept API的全部功能,我认为很明显它实际上是多么惊人!
我希望这篇文章能让你对概念API有一个全面的了解,并激励你用它来创建更多的东西!
如果你想快速测试这个项目,你可以从我们的克隆它GitHub回购.