使用概念API创建一个测试与JavaScript
概念是多功能的应用用于组织各种内容,从笔记到日历和提醒。在上一篇文章中,开始概念API和它的JavaScript SDK,我们深入研究了如何使用concept的API,并创建了一个与之交互的小界面。本文现在将探索concept API的另一个用例:创建一个JavaScript测试。
虽然阅读本文不需要任何相关知识(我将提供所有必需的步骤),但我们将处理前端和后端代码,因为涉及到一些Node.js和Express设置,因此假定您具有一些JavaScript技能。
JavaScript测试项目设置
我们将把设置分成两个部分。在第一部分中,我们将在concept端完成所需的设置,在第二部分中,我们将使用我们的代码。
要继续学习,您需要一个concept帐户(下文将详细介绍),以及一份最新的节点安装在您的机器上.一如既往,本教程的最终代码可以在GitHub上找到.
概念设置
如果您还没有一个概念帐户,请按以下步骤创建一个这个链接.创建帐户并登录后,通过选择创建一个新页面添加页面给它起个名字。在本教程中,我们将使用a表格
数据库。虽然它不是构建测试的理想数据库,但它是我们用concept !
向表中插入信息
现在我们有了空的表格
,我们需要弄清楚如何正确地将我们的信息插入其中。
我们的测试计划如下:
{“1”:{“问题”:“JavaScript的目的是什么?”,“答案”:{“1”:为HTML页面设置样式,“2”:“为HTML页面添加交互性”,“3”:"执行服务器端脚本操作"},“正确”:“为HTML页面添加交互性”},“2”:{“问题”:“要将JavaScript插入HTML页面,使用哪个标签?”,“答案”:{“1”:“<脚本=“java”>”,“2”:javascript“< >”,“3”:“< >脚本”},“正确”:“< >脚本”},“3”:{“问题”:"在网页上写" Hello World "时,下列哪个选项正确?",“答案”:{“1”:“打印”(“Hello World”),“2”:”文档。写(“Hello World”)”,“3”:”反应。写(“Hello World”)”},“正确”:”文档。写(“Hello World”)”}}
概念我sn’t really built for this type of database, so we need to get creative with it! So our问题
列就是a标题
(这很有效)和我们的正确的
列将是类型文本
(这也可以正常工作)。然而,对于我们的多种选择,我们需要做一些不同的事情!我的方法是使用同时选中
字段类型,所以我可以写多个结果到相同的单元格(我们将看到路径下的数据检索从这看起来像)。所以我们的表格
最终结果应该如下图所示。
创建我们的概念API集成
现在我们需要转到概念API网站来求积分。按下我的集成按钮,然后点击创建新的集成.我们需要填写我们的标题,并确保选择我们的关联工作区(它将在默认情况下被选择,但请确保这一点)。如果我们按提交,我们将被引导到一个带有内部集成令牌的新页面(我们将在代码中使用它),并且有两个选项框用于我们想要在哪里使用集成。除了复制标记并按下,我们不需要在此页上做任何事情保存更改.
现在我们回到我们的concept工作区。在新创建的concept数据库中,我们希望按分享,然后邀请.然后我们就可以选择新创建的积分了。如果我们选择它并按邀请,我们的概念设置就完成了。做得好!
代码设置
对于我们的代码设置,我们将使用一个概念模板存储库(然后我们可以在任何我们的概念API项目中使用!),该存储库已经具有使用概念API所需的初始代码。这个回购可以找到在这里,所以一定要fork它和克隆它,以配合我们的项目!如果您对所有代码的功能感兴趣,请参阅“开始概念API和它的JavaScript SDK,因为我们对每一段代码都进行了大量的详细说明(repo也有一个自述
这应该解释了它的功能!)
安装依赖关系
在fork和克隆我们的concept模板repo之后,我们的第一步是安装我们的依赖项,所以确保运行纱
或npm安装
在我们的终端文件夹内。在这个项目中,我们有三个依赖项:@notionhq /客户端,dotenv而且表达.我们将使用dotenv来管理变量并保证它们的安全(例如我们在集成中看到的变量),并使用Express为应用程序创建后端和服务器。
要使用dotenv管理变量,请创建一个.env
在我们的项目的根文件,并粘贴以下文件:
NOTION_API_KEY=YOUR_TOKEN_HERE NOTION_API_DATABASE=YOUR_DATABASE_ID_HERE
我们的NOTION_API_KEY
我们能在我们的集成,而我们的NOTION_API_DATABASE
可以通过转到创建的概念页面并查看浏览器的URL栏来找到。它出现在您的工作区名称(如果我们有的话)和斜杠(myworkspace /
)和问号(?
).ID长度为32个字符,由数字和字母组成:
https://www.notion.so/myworkspace/a8aec43384f447ed84390e8e42c2e089?v=...|---------数据库ID --------|
如果我们担心将concept的API密钥放在repo中的文件上,请注意.gitignore
我们有.env
文件;的.gitignore
允许我们在里面放置不同的文件/文件夹名称,这意味着当我们推送代码时,这些文件/文件夹不会被添加到我们的repo中。
现在我们已经有了初始存储库,并从concept获得了所需的凭据,我们可以开始进行测试了!
抓取JavaScript测试数据
我们应该首先检查是否成功连接到我们的concept数据库,因此我们将导航到我们的.index.js
档案和记录我们的响应
变量(看我们如何抓取databaseId
从我们的.env
文件和使用它在我们的数据库查询吗?)
如果我们跑纱线开始
,我们应该在终端上看到如下截图。
在终端上看到这一点意味着我们已经正确地连接到我们的concept数据库,现在我们可以获得所需的数据了。我们的getDatabase
函数看起来是这样的:
出口.getDatabase=异步函数(){常量响应=等待概念.数据库.查询({database_id:databaseId});常量responseResults=响应.结果.地图((页面)= >{返回{id:页面.id,问题:页面.属性.问题.标题[0].plain_text,答案:页面.属性.答案.multi_select,正确的:页面.属性.正确的.rich_text[0].plain_text,};});返回responseResults;};
与responseResults
,我们映射到结果
(匹配数据库中的条目),我们将不同属性的路径映射到我们所选择的名称(在本例中,id
,问题
,答案
而且正确的
).注意对象路径是多么特定。这是经过设计的,这意味着在开发和使用您自己的数据库时,您应该不断地调查返回的属性,直到找到您正在寻找的信息为止(这实际上是一个反复试验的问题)。
有了这个新代码,我们基本上调用了API,并选择了我们想要在代码中使用的属性,这意味着我们已经准备好在接口上使用它们了!
在浏览器中显示数据
让我们从处理HTML和CSS开始,因为它们非常直接!我们不会对模板中的HTML和我们的style.css
我们可以将下面的代码粘贴到现有代码的下面:
.questionContainer{填充:30.px;显示:flex;flex-direction:列;justify-content:中心;对齐项目:中心;不必:rgba(149,157,165,0.2)0px8px24px;这个特性:10px;}.numberElement{保证金:0px汽车10px;字体大小:12px;粗细:700;首字母:大写字母;}.question{保证金:0px汽车40px;}.answersDiv{宽度:One hundred.%;显示:flex;flex-direction:列;差距:20.px;}.answerOption{填充:20.px;保证金:0px;字体大小:18px;text-align:中心;光标:指针;边境:1px固体rgb(42,43,44);这个特性:40px;}
我们还不会看到这些样式的变化,但现在我们可以关注功能,这是本教程中更重要的部分。
如果我们现在去main.js
文件内的公共
文件夹,我们会看到我们已经从后端用getDataFromBackend
函数。如果你对此感到困惑,”开始概念API和它的JavaScript SDK有一个更长的解释,但基本上是在我们的server.js
我们创建了一个获取数据库的路由,在这里getDataFromBackend
我们正在做一个获取
到同一条路线,它会为我们抓取数据。
注意里面addData
我们已经有了const data = await getDataFromBackend();
.这意味着我们已经准备好开始处理我们的数据了,我们实际上可以检查这一点!日志
这数据
变量,我们应该在控制台上看到数据库项的数组。
在屏幕上显示我们的数据
现在我们知道了返回的数据是什么样子,我们需要考虑如何在屏幕上显示它。我的想法是每个问题都有一张卡片,里面有不同的答案,当用户按下正确的答案,答案的背景应该转绿色;如果它是错误的,它应该会转红色的.
让我们从创建一个< div >
对于每个问题。我们可以用a遍历数组forEach
循环,允许我们创建< div >
并添加一些类。
在我们的addData
函数我们可以这样做:
常量addData=异步()= >{常量数据=等待getDataFromBackend();数据.forEach((价值,指数)= >{常量div=文档.createElement(“div”);div.班级名册.添加(“questionContainer”);容器.附加(div);});};
但它仍然感觉有点空,所以让我们为每张卡片附加一个标题,像这样:
常量addData=异步()= >{常量数据=等待getDataFromBackend();数据.forEach((价值,指数)= >{常量div=文档.createElement(“div”);div.班级名册.添加(“questionContainer”);常量numberElement=文档.createElement(“p”);numberElement.班级名册.添加(“numberElement”);numberElement.innerHTML=`问题$ {指数+1}`;div.列表末尾(numberElement);容器.附加(div);});};
这里我们创建一个< p >
给它上一节课,我们正在研究索引+ 1
,因为JavaScript中的数组是从零开始的,我们不想看到问题0,因为这没有意义!如果我们现在启动我们的应用程序,我们应该会看到如下图所示的东西。
有趣的部分是:呈现问题和答案的新功能
现在开始有趣的部分!我们可以在里面做所有的逻辑运算addData
,但这可能会太混乱,所以我们将创建新的函数来渲染我们的问题而且答案.
让我们从问题,让我们做一些工作addData
仍然不会转化为太多的函数:
常量addData=异步()= >{常量数据=等待getDataFromBackend();数据.forEach((价值,指数)= >{常量div=文档.createElement(“div”);div.班级名册.添加(“questionContainer”);常量numberElement=文档.createElement(“p”);numberElement.班级名册.添加(“numberElement”);numberElement.innerHTML=`问题$ {指数+1}`;div.列表末尾(numberElement);//我们新添加的代码常量问题=createQuestion(价值.问题);div.列表末尾(问题);//结束我们新添加的代码容器.附加(div);});};
我们刚刚添加的代码与numberElement
,但这里我们将一个函数赋值给一个变量,并附加该变量。注意我们正在经过value.question
到我们的createQuestion
,因为我们想要使用和渲染问题当然。一切很快就会明白的——别担心!
现在,外面和上面addData
,让我们创建这个新的createQuestion
函数。在它里面,我们需要的逻辑与我们为numberElement
:创建一个元素,给它一个类,并添加一些内容。这里我们用notinnerHTML
但createTextNode
:因为我们的问题与代码有关,如果我们要使用innerHTML
就像< b > < / b >文本
,它实际上会呈现这个词文本
但是用粗体代替了整个语法(您可以看到一个例子在这里).我们最后的createQuestion
会是这样的:
常量createQuestion=(问题)= >{常量questionElement=文档.createElement(“h3”);questionElement.班级名册.添加(“问题”);常量questionNode=文档.createTextNode(问题);questionElement.列表末尾(questionNode);返回questionElement;};
如果我们现在运行纱线开始
,我们的浏览器应该如下所示。
现在我们来建立答案基本上是一样的。我们先做和之前一样的事情createQuestion
内部addData
:
常量addData=异步()= >{常量数据=等待getDataFromBackend();数据.forEach((价值,指数)= >{常量div=文档.createElement(“div”);div.班级名册.添加(“questionContainer”);常量numberElement=文档.createElement(“p”);numberElement.班级名册.添加(“numberElement”);numberElement.innerHTML=`问题$ {指数+1}`;div.列表末尾(numberElement);常量问题=createQuestion(价值.问题);div.列表末尾(问题);//我们新添加的代码常量答案=createAnswers(价值);div.列表末尾(答案);//结束我们新添加的代码容器.附加(div);});};
现在我们开始寻找createAnswers
会是这样的:
常量createAnswers=(价值)= >{常量answersDiv=文档.createElement(“div”);answersDiv.班级名册.添加(“answersDiv”);返回answersDiv;};
注意我们是怎么做的const answers = createAnswers(value);
.我们不能就这么过去value.answers
对我们的函数,因为我们还需要value.correct
.我们可以向函数传递两个参数:一个是数组of答案另一个是正确的一个。
呈现答案数组
我们现在有一个数组答案,我们需要渲染所有的,所以我们需要一个循环来遍历所有的。这个循环中的过程将与所有其他元素的过程几乎相同,所以我们应该如此优点此时在DOM上渲染元素:
常量createAnswers=(价值)= >{常量answersDiv=文档.createElement(“div”);answersDiv.班级名册.添加(“answersDiv”);为(让我=0;我<价值.答案.长度;我++){常量answerElement=文档.createElement(“p”);answerElement.班级名册.添加(“answerOption”);常量answerNode=文档.createTextNode(价值.答案[我].的名字);answerElement.列表末尾(answerNode);answersDiv.列表末尾(answerElement);}返回answersDiv;};
在这段代码中,我们循环遍历数组
,创建一个元素,给它一个类和使用createTextNode
为了呈现我们的答案.(有趣的是,如果我们使用innerHTML
在这里,答案与< >脚本
不会渲染。)然后我们只是把这个加起来answerNode
对我们的< p >
然后把这个附加到我们的< div >
!如果我们逃跑纱线开始
,我们现在将看到完整的测试!哇!
与答案互动
嗯,但是我们不能真正与答案互动,如果我们不知道我们的答案是对还是错,这就不是真正的测试,对吧?我们应该解决这个问题!
我们知道我们想要点击每一个回答知道它是不是正确的或错误的,所以我们可以开始添加一个事件监听器,如下所示:
常量createAnswers=(价值)= >{常量answersDiv=文档.createElement(“div”);answersDiv.班级名册.添加(“answersDiv”);为(让我=0;我<价值.答案.长度;我++){常量answerElement=文档.createElement(“p”);answerElement.班级名册.添加(“answerOption”);常量answerNode=文档.createTextNode(价值.答案[我].的名字);//我们新添加的代码answerElement.addEventListener(“点击”,()= >{});//结束我们新添加的代码answerElement.列表末尾(answerNode);answersDiv.列表末尾(answerElement);}返回answersDiv;};
记得我们做过createAnswers(值)
,这样我们就可以得到value.correct
?现在是发光的时候了!当我们点击一个答案时,有两种可能的结果:用户选择了等于正确答案的答案,或者用户选择了不等于正确答案的答案。为了处理这些可能的结果,我们将使用if语句,以及我们将向用户显示他们得到了答案的方式正确的或错误的是通过一种改变吗背景颜色
答案。所以我们的逻辑是这样的:
常量createAnswers=(价值)= >{常量answersDiv=文档.createElement(“div”);answersDiv.班级名册.添加(“answersDiv”);为(让我=0;我<价值.答案.长度;我++){常量answerElement=文档.createElement(“p”);answerElement.班级名册.添加(“answerOption”);常量answerNode=文档.createTextNode(价值.答案[我].的名字);answerElement.addEventListener(“点击”,()= >{//我们新添加的代码answerElement.风格.颜色=“白色”;如果(价值.答案[我].的名字= = !价值.正确的){// color我们的answerElement红色answerElement.风格.写成backgroundColor=“# f55142”;}其他的{// color我们的answerElement绿色answerElement.风格.写成backgroundColor=“# 6 dbf39”;}//结束我们新添加的代码});answerElement.列表末尾(answerNode);answersDiv.列表末尾(answerElement);}返回answersDiv;};
每次点击,我们都将文本颜色改为白色,然后我们检查是否的名字
每个答案的属性等于value.correct
(这显然不是理想的,索引会更好,但我们已经尽力使用了concept的数据库!)如果不是,我们把它的颜色改为红色,如果是,我们把它改为绿色!
And that’s our quiz done! Isn’t it fantastic?
概念JavaScript测试概述
在本教程中,我们探索了concept API提供的许多功能,老实说,看到您可以使用这样一个简单的工具做这么多事情总是非常令人兴奋的!
我希望这篇文章最终能激励你探索concept API,并用concept构建你自己的测验和其他有趣的东西!
如果您想快速测试这个concept项目,您可以从我们的GitHub回购.