前言

当我们把数据手动输入到原型中可能会很慢,很忧伤。但是,为了让原型看起来更真实,我们需要手动输入很多真实的数据。我们可以使用API来实时获取json数据,刚开始可能会有点难,但是能使用时,你会发现,他是多么的方便。

工具

realdata.dev

官网地址
这个是framer X的一个设计师弄的网站。可以生成自己需要的API,它里面也提供了一些API接口,并且这个网站也有教如何在Framer X使用API来填充数据。

模客

官网链接
这个呢,也是一个可以生成API接口的一个网站。国内的,上面那个是国外的。

ApiPost

官网链接
ApiPost是一个支持团队协作,并可直接生成文档的API调试、管理工具。支持模拟POST、GET、PUT等常见请求,是后台接口开发者或前端、接口测试人员不可多得的工具。
我们用这个呢,主要是可以看看我们生成的API接口里面有什么,或者我们的API接口对不对。

在线JSON格式检验

链接
这个呢,主要是检测我们写在API里面的JSON对不对,起一个检测的作用。如果JSON写错了,API返回的东西,也是错的。

AirTable

AirTable
Airtable 是新型的表格制作工具,可以把文字、图片、链接、文档等各种资料聚合在一起,成为我们的私人定制资料库。他比较特别的地方在于他的API,我们可以通过调用他的API,来使用表格里面的数据。

什么是API

API是一台计算机与另一台计算机通信的接口。因为计算机不需要可视元素(如按钮)进行通信,所以API基本上只是来回发送的文本字符串-请求和响应。

image.png

设计师专用API

实际工作中,API的请求是很复杂的,要用到token,等很复杂的东西。作为设计师的我们,我们仅仅需要JSON数据来填充我们的原型。换句话说就是, 我们的API里面只有简单的JSON数据就可以。

为此:我发现了两个不错网站。

  • 模客
  • realdata.dev

//模客这里说一下
模拟环境运行中,将你要访问的api的地址改为http://mock-api.com/*********.mock/{your-api-url}后,正常运行程序即可。

这两个可以允许设计师,简答的构建API,简答的使用。具体的使用过程就不说了,自己摸索就挺简单的。

//这个是realdata.dev

image.png

//这个是模客

realdatasite@2x.jpg

使用我们搭建好的API

1: Fetching the Data

我们可以使用 fetch() 功能获取他们
**

  1. fetch("http://mock-api.com/0ZzR0mne.mock/api/cat")

2: Fetch Returns a Promise

fetch()耐心地等待API响应的同时,我们其余的代码也会在不经意的情况下继续运行。如果我们尝试在API响应之前使用数据,则会得到undefined

const data = fetch("http://mock-api.com/0ZzR0mne.mock/api/cat")
console.log(data) // undefined

那是因为fetch()是一个异步函数,该函数返回一个称为Promise的特殊对象。当API响应时,此Promise对象会自动更新。这样做的想法是fetch() 承诺一旦数据到达就交出数据,但是由于这可能要花很长时间,因此我们不应该在等待时停止其他所有操作。

fetch("http://mock-api.com/0ZzR0mne.mock/api/cat")
  .then(response => {
    console.log("We got the data!", response)
  })

当API响应时,数据将传递给该.then()方法。我们通过传递.then()带有单个参数的函数来访问数据response

3: Extract JSON from the Response

我应该注意的是,response其中不仅包含我们正在寻找的cats 数据。它实际上是一个特殊的Response对象,具有自己的属性和方法。其中一种方法是.json(),我们将使用该方法以可以使用的格式提取数据。

fetch("http://mock-api.com/0ZzR0mne.mock/api/cat")
  .then(response => response.json())
  .then(data => {
    console.log("Ok, now we really have the data!", data)
  })

4:Save the JSON to State

const [data, setData] = useState(null)

useEffect(() => {
  fetch("http://mock-api.com/0ZzR0mne.mock/api/cat")
    .then(response => response.json())
    .then(data => {
      setData(data)
    })
}, [])

使用JSON文件:

目前为止,我们已经成功的从API拿到了我们想要的JSON数据。但是面对这个庞然大物,我们应该怎样去使用他们呢。

点表示法。

想象一下,您告诉同事在共享文件夹中打开特定文件。您可能会大喊“打开Design文件夹,然后在其中打开一个Website Redesign文件夹,然后在其中打开第三个Sketch文件。”
同样,点表示法是我们告诉计算机浏览JSON数据的方式。

const author = {
  name: {
    first: 'Zach',
    last: 'Johnston'
  },
  age: 28,
  location: 'New York'
}

// Example 1
console.log(author.age)          // 28

// Example 2
console.log(author.name.first)  // 'Zach'

// Example 3
console.log(author.location)    // 'New York'
console.log(author['location']) // 'New York'

括号符号和数组

在上面的示例中,我们使用名称来指定键,但是如何处理数组?数组项不是键值对,因此要定位这些未命名的对象,我们引用它们在数组中的位置。

const authors = [
  { name: 'Zach' },
  { name: 'Brendan' },
  { name: 'Hunter' }
]

// Example 1
console.log(authors[0].name)  // 'Zach'

串在一起

const artist = {
  name: 'Taylor Swift'
  albums: [
    {
      name: 'Lover',
      tracks: [
        { name: 'I Forgot That You Existed' },
        { name: 'Cruel Summer' },
        { name: 'Lover' }
      ]
    }
  ]
}

console.log(artist.name)                     // 'Taylor Swift'
console.log(artist.albums[0].name)           // 'Lover'
console.log(artist.albums[0].tracks[1].name) // 'Cruel Summer'

映射数据

我们已经知道怎么从API获取数据,以及如果使用JSON文件,让我们一起搭建页面吧。

截屏2019-12-13上午8.56.07.png

设计组件:

我们首先要设计一个组件,以便于数据可以按照这个组件,进行填充。‘

image.png
我们把设计文件变成组件之后,要弄好命名,这个在我们之后遍历json数据的时候要用到,就是红箭头指着的地方。

四种方法:

我们将采用四种方法,来遍历我们准备好的JSON数据。

  • code内声明JSON,然后遍历
  • 将JSON文件导入到项目的Code中,然后导入tsx文件中,遍历
  • 利用API,请求JSON文件,然后遍历
  • 利用组件商店里面的Data Stack,可以导入json文件,也可以使用API链接。

image.png
一共四种方法,不管用哪种,都要保证你的json文件格式是正确的。!!!这个很重要。如何判断正误,可以通过上面的工具,ApiPost和在线JSON格式检验来看看。

第一种:组件内声明JSON

import * as React from "react"
import { Stack } from "framer"
import { Cat } from "./canvas"

//定义一个数组
//数组里面的名字就和我们设计组件中的图层的命名是要一样的。
const list = {
    catListContent: [
        {
            index: 0,
            Photo: "http://nangong.sc2yun.com/cat/1.png",
            Primary: "布偶猫",
            Secondary: "谁还不是一小可爱了呢",
        },
        {
            index: 1,
            Photo: "http://nangong.sc2yun.com/cat/2.png",
            Primary: "kitty猫",
            Secondary: "谁还不是一小可爱了呢",
        },
        {
            index: 2,
            Photo: "http://nangong.sc2yun.com/cat/3.png",
            Primary: "加菲猫",
            Secondary: "谁还不是一小可爱了呢",
        },
        {
            index: 3,
            Photo: "http://nangong.sc2yun.com/cat/4.png",
            Primary: "蓝白",
            Secondary: "谁还不是一小可爱了呢",
        },
        {
            index: 4,
            Photo: "http://nangong.sc2yun.com/cat/5.png",
            Primary: "kitty猫",
            Secondary: "谁还不是一小可爱了呢",
        },
        {
            index: 5,
            Photo: "http://nangong.sc2yun.com/cat/6.png",
            Primary: "田园猫",
            Secondary: "谁还不是一小可爱了呢",
        },
        {
            index: 6,
            Photo: "http://nangong.sc2yun.com/cat/7.png",
            Primary: "虎斑猫",
            Secondary: "谁还不是一小可爱了呢",
        },
        {
            index: 7,
            Photo: "http://nangong.sc2yun.com/cat/8.png",
            Primary: "kitty猫",
            Secondary: "谁还不是一小可爱了呢",
        },
        {
            index: 8,
            Photo: "http://nangong.sc2yun.com/cat/9.png",
            Primary: "kitty猫",
            Secondary: "谁还不是一小可爱了呢",
        },
        {
            index: 9,
            Photo: "http://nangong.sc2yun.com/cat/2.png",
            Primary: "kitty猫",
            Secondary: "谁还不是一小可爱了呢",
        },
    ],
}

export function Lists() {
    //遍历数组
    const CatList = list.catListContent.map((catListContent, index) => {
        return (
            <Cat
                key={catListContent.index}
                Primary={catListContent.Primary}
                Secondary={catListContent.Secondary}
                Photo={catListContent.Photo}
            />
        )
    })
    return (
        <Stack gap={0} distribution="start" width={"100%"}>
            {CatList}
        </Stack>
    )
}

第二种:将JSON文件导入到项目的Code中,然后导入tsx文件中,遍历

  • 首先按住command + shift + P 打开项目的文件夹。
  • 把我们准备好的json文件放到其中的Code文件夹中。
  • 然后在代码中引入这个json文件,进行遍历。

image.png
项目文件夹中的code文件夹
image.png
将JSON文件复制到code文件中。

import * as React from "react"
import { Stack, addPropertyControls, ControlType } from "framer"
import { Cat } from "./canvas"
//@ts-ignore
import { catListContent } from "./cat.json"

//@ts-ignore  这个是个好东西啊。我导入json那个是按照官网弄的,但是会报错,头疼啊。但是加个这个就好了。嘿嘿
export function ProjectLists() {
    //遍历数组
    const CatList = catListContent.map((catListContent, index) => {
        return (
            <Cat
                key={catListContent.index}
                Primary={catListContent.Primary}
                Secondary={catListContent.Secondary}
                Photo={catListContent.Photo}
            />
        )
    })
    return (
        <Stack gap={0} distribution="start" width={"100%"}>
            {CatList}
        </Stack>
    )
}

把json文件中,我们需要的数据导入进来

第三种:利用API,请求JSON文件,然后遍历

如上文的工具中说的,我们可以用模客或者realdata.dev把我们的json数据,生成API链接,或者通过技术人员,调取到我们需要的真实数据。这个比较灵活。

做之前我们要确认几个事。

  • 第一:我们的JSON格式是正确的。
  • 第二:我们API返回的数据是没有问题的。

image.png
通过apiPost可以看看我们API返回的数据是怎样的,到底有没有错误。如果这一步就错了,后面API遍历是很头疼的。

import * as React from "react"
import { Frame, Stack } from "framer"
import { useState, useEffect } from "react"
import { Cat } from "./canvas"

export function ApiLists() {
    //从API中获取JSON
    const [data, setData] = useState(null)
    useEffect(() => {
        fetch("http://mock-api.com/0ZzR0mne.mock/api/cat")
            .then(response => response.json())
            .then(data => {
                if (data.catListContent) {
                    setData(data.catListContent)
                }
            })
    }, [])

    //如果数据还没有返回值,则返回loading
    if (!data) return <Frame>Loading...</Frame>

    const { catListContent = [] } = data
    //遍历数组
    const CatList = data.map((catListContent, index) => {
        return (
            <Cat
                key={catListContent.index}
                Primary={catListContent.Primary}
                Secondary={catListContent.Secondary}
                Photo={catListContent.Photo}
            />
        )
    })
    return (
        // @ts-ignore
        <Stack gap={0} distribution="start" width={"100%"}>
            {CatList}
        </Stack>
    )
}

第四种:Data Stack,可以导入json文件,也可以使用API链接。

这个组件主要支持JSON文件导入和API链接。
image.png
我们接下来简单的说一下这个组件怎么用。

image.png

  • 首先啊,我们要像之前那样,建立一个参考对象,然后变成组件,把组件里面各个图层命名好,然后根据图层的名字去弄JSON文件和API链接。
  • 第二,然后把json文件或者api链接放到Source那里,其他的设置一下。
  • 将大框连接一下小的设计组件。大功告成。

第五种:airTable

我们在airtable里面存好我们的数据,通过API的方式,用组件商店里的airtable组件来实现把数据体现在原型上。重点说一下airtable 和 DataStack的区别。

dataStack

可以通过API 或者 json文件形式来处理数据。按照我们之前的操作,我们想长期维护一组数据,需要用在线excal工具更改,然后复制excel的数据,通过 在线json转换工具,把excal中的东西转换成json代码,然后再更改模客里面的数据,从而来刷新API。

airTable

这个可以通过在airtable中更新我们的数据,然后直接通过自带的API来刷新数据,这样就省去了变json,改api的步骤,还是蛮不错的。

使用方法

  1. 首先,我们要在airtable中建立一组自己的数据。(注意:数据的列名称要和你在framer设计组件的名字是一样的)

image.png

  1. 其次,在我们自己的账户里面设置我们的API key,这个比较重要,不要轻易泄漏。

image.png

  1. 然后,我们需要调取我们该文档的API。 airTable API ,进入该API界面,选择我们需要获取API的表格。

image.png

  1. 点击右上角的show api,可以在API文档里面显示自己的api token。我们需要的就是红色框框选中的那些代码,这个就是我们需要的API链接。

image.png

  1. 把这个复制到我们的Airtable中的输入API的位置就可以啦。

使用技巧

此时,我们发现,framer中airtable中的顺序和我们在airtable中的顺序不一样。头疼啊,后来我去咨询了一下,设计airtable组件的那个framer的官方设计师,她回答说只要在我们请求的api链接添点代码,就可以实现顺序是一样的。

我们请求的API链接是这样:
https://api.airtable.com/v0/app6I58LfuNihimLf/Menu?api_key=YOUR_API_KEY
这个时候顺序是random的,我们只需要在 menu? 和 api_key 中间添加 &view=Grid%20view&

像下面这样 :

https://api.airtable.com/v0/app6I58LfuNihimLf/Menu?&view=Grid%20view&api_key=YOUR_API_KEY

顺序就一样啦。

如果我们在apipost中看一下的话,是这样子的。他的原理实际是多传递了一个view的参数。

image.png

image.png

上面这个图是framer 社区原作者的一些答疑。链接 —> 链接

第六种 csv数据类型

这个我是把组件商店里面的google sheet改造了,它的原理也是解析csv文件。我尝试了很多遍,并不行。所以就改了一下其中的代码。现在可以支持 本地CSV文件(这个可以用Excel导出) 和 html形式的csv文件。
这个组件我并没有发布,所以使用的话有难度。
你得安装 papaparse ,用npm 或者 yarn安装
然后还得用我这个文件

源文件:

05 CSV-Sheets.framerx.zip

总结

不管我们用json也好,api也好,都是为了让我们的设计原型看起来更真实。api要难一点,真正会用了,会更简单。
我们脑补一个简单的场景,你把你做好的原型生成了链接,然后放到了服务器上。你依然可以通过更改API里的内容,来更改你的设计原型。酷吧。好好学习吧。

参考网站和源文件:

Framer X官网API教程
Bringing Prototypes to Life With Data

官网文件:
designing-with-apis.zip

我的文件:
API-real data.framerx.zip

增加Data stack
API-real data.framerx.zip

增加airtable

API-real data.framerx.zip