欢迎各位兄弟 发布技术文章
这里的技术是共享的
在 Drupal 8 的 REST API 这个课程里,我们已经介绍了 REST API 的基本的使用,你应该已经了解了,想要得到具体的资源,需要怎么去发出请求,请求回来的资源是什么样儿的 ...
下面我们会在一个 React Native 项目里使用一下这些资源 .. 我们在 React Native 的相关课程里做了一个小项目,名字是 movietalk,你可以在宁皓网的 github 仓库里找到这个项目 .. 把它克隆到本地,然后我们接下来会去改造一下它,把项目用的后端替换成 Drupal 。
介绍与准备
1)介绍
下面我们会在一个 React Native 项目里使用一下这些资源 .. 我们在 React Native 的相关课程里做了一个小项目,名字是 movietalk,你可以在宁皓网的 github 仓库里找到这个项目 .. 把它克隆到本地,然后我们接下来会去改造一下它,把项目用的后端替换成 Drupal 。
下面我们先去把 React Native 课程里创建的一个小项目克隆到本地的电脑上 .. 打开 终端 ...
先进入到某个目录的下面 .. 然后输入 git clone https://github.com/ninghao/movietalk
完成以后,需要再去安装一下项目需要的一些东西 .. 先进入到这个目录的下面 .. 然后输入 npm install
这需要等一段时间 .. 因为需要下载的东西比较多 ..
完成以后 .. 查看一下当前的分支 .. git branch ... 显示现在所在的分支是 master .. 再查看一下提交的日志 ..
最后一次提交是 获取用户资料时的加载指示器 .. 因为以后我们可能会继续去更新这个项目 .. 很可能你在看到这个视频的时候,可能代码会有一些变化 ..
这样我们可以基于这里显示的这个最后一次提交去创建一个新的分支 .. 然后所有的修改都在这个新的分支上去做 ...
先复制一下这里最后一次提交的 id 号 .. 下面我们使用这个提交作为起点,去创建一个新的分支 .. 然后再切换到这个新的分支上 .. 输入 git checkout -b .. 先加上一个分支号 .. 名字可以是 drupal-8 .. 这样会切换到这个分支 .. 如果这个分支不存在就会去创建一个 ..
后面我们再加上一个提交的 id 号 .. 意思就是用这个提交作为一个起点去创建一个新的分支 ..
git checkout -b drupal-8 9fa13fd
查看一下当前所在的分支 .. git branch .. 显示现在是在 drupal-8 这个分支上 ..
这个课程我们需要用到 Drupal 作为后端的服务,然后前面还要使用 React Native 这个项目,所以需要在本地电脑上同时运行它们。
在我的桌面上,有一个 web-stack,这是在 Web 运行环境里搭建的环境,在 Drupal 的课程里我们在这个环境上安装了一个 Drupal 8 。
进入到这个目录 .. 启动一下虚拟机 ... 再连接到这个虚拟机 ...
然后再去运行一下上一个视频里准备好的 React Native 项目 .. 打开 movietalk .. ios .. 打开这里的 xcode 项目文件 ...
选择要项目要运行的设备 .. 然后再运行一下 ... 这样会打开 iOS 的设备模拟器,在上面运行这个项目 ..
command + D .. 打开开发菜单 ... 然后启用一下实时预览的功能 .. enable live reload ...
然后我们再用编辑器打开这个 React Native 项目 ...
这里我用的是 Atom 编辑器 .. command + O .. 选择在桌面上的这个 movietalk 目录 ...
先修改一个地方 .. 打开 index.ios.js ..
把应用默认打开的页面设置成 featured ... 再保存一下 .. 现在你会看到,模拟器上默认会打开推荐电影这个页面 .. 现在这里显示的数据来源是豆瓣的 API 提供的 .. 我们需要把它替换成 Drupal 的 REST API ...
这个推荐电影里面用的是 Featured 组件 .. 打开 Featured.js ... 在这个组件里面,设置了默认的路由要打开的组件,这里就是 MovieList .. 再打开 app 目录下的 MovieList.js ..
在这个组件里,我们使用了豆瓣的 API ,使用 fetch 这个方法请求回来一些电影内容,把这些内容作为数据源交给了 React Naitve 的 ListView 组件去使用。 如果你还不了解具体怎么做,可以参考宁皓网关于 React Native 的课程。
在介绍 Drupal 8 的 REST API 的时候,我们创建了一个 REST 视图 .. 地址是 api/movie .. 先看一下,使用 POSTMAN 请求一下这个地址 .. 先是网站的基本地址 .. 加上一个 /api/movie ...
它会给我们返回来一些数据 ... 这些数据里面只有一个属性 .. 就是这个 title .. 在后面我们会再去编辑一下这个视图,让它输出更多的内容 ...
回到编辑器 .. 这里的 this.REQUEST_URL 就是在组件里面要请求的地址,现在用的是豆瓣的 api .. 我们把它替换成 Drupal 的 REST API .. 地址是 Drupal 网站的基本地址 .. 加上 /api/movie ..
this.REQUEST_URL = 'http://web-stack.drupal-8.ninghao.local/api/movie';
再找到 requestURL ,这个方法可以返回需要请求的地址,因为要请求的地址里面可能会包含一些参数 .. 使用这样的一个方法会更方便一些 .. 先去掉这里的 count 还有 start 参数 .. 这些是专门针对豆瓣的 API 添加的东西 .. 主要的功能就是去处理分页内容 ..
方法返回的东西,先只留下这个 url ..
再浏览到 fetchData 这个方法,它的功能主要就是获取到一些初始的数据,也就是先要去请求一下我们提供的 API 的地址,把得到的内容交给 ListView ..
去掉这个 newStart 变量 .. 下面设置的是组件的状态 .. 只留下这个 movies 状态,还有 loaded 状态 .. total 还有 start 这两个状态都是针对豆瓣的 api 设计的 ..
再修改一下要交给 movies 状态的值,去掉后面的 .subjects ,因为我们请求回来的数据直接就是电影内容,并没有在这个 subjects 属性里面 ... 这里只用一个 responseData ..
显示每个数据源,用的是 renderMovieList 这个方法 .. 每一个显示的列表项目用的是 movie 来表示的 .. 现在我们要显示的是电影的海报 ... 电影的标题 .. 原始的名字 .. 年代 .. 还有评分 ..
不过现在,在我们的 drupal rest api 里面,每个项目里面只有一个标题属性 .. 名字就是 title ,所以,暂时我们只能显示出这个属性里的东西 ...
先注释掉其它的东西 .. 电影的海报 .. 电影的原始名 .. 电影的年代 .. 还有这个平均分 .. 只留下这个 movie.title ..
保存一下 .. 启用了项目的实时预览功能以后,文件有变化的时候,会自动刷新应用的显示 .. 现在你会看到,在这个推荐电影页面上,会显示一些电影的标题 ... 这些数据就是我们的 Drupal 提供的。
现在请求这个 Drupal 提供的资源地址,在返回来的数据里面,只有一个 title 属性 .. 下面我们给去添加几个项目 .. 回到 Drupal 的管理后台 .. 打开 结构 .. 视图 .. 找到我们在介绍 Drupal REST API 的时候创建的这个名字是 REST 的视图 ..
在这个 REST Export 视图显示里面,现在只有一个标题字段 ... 再去给它添加几个字段 .. 先找到 电影名 ... 再找到 发行日期 ... 还有一个电影海报字段 ...
应用一下 .. 现在让我们配置一下 发行日期 这个字段 .. 格式化 这里选择 自定义 .. 然后在下面可以自定义日期的显示格式 .. 这里只留下一个大写的 Y ,他是用 4 位数字表示的年份 ..
再点击应用 .. 这回要配置一下电影的海报这个字段 .. 图像样式选择 中号海报 .. 这些字段还有图像样式都是我们在介绍 Drupal 的字段的课程里创建的 ..
再应用一下 .. 电影名这个字段不需要特别的配置,直接点击应用 ..
这里可能有个 bug ,就是有时候在批量添加字段的时候,对字段的配置可能没有保存 .. 打开这个 发行日期 .. 重新再配置一下 .. 在日期格式这里,只留下一个大写的字母 Y ..
保存一下这个视图 .. 回到 POSTMAN ,重新再请求一下这个地址 ...
这回在返回的数据项目里面,除了 title ,还有几个新的属性 .. field_release_date ,电影的发行日期 .. field_poster ,电影的海报 .. field_name ,电影的名字 .. 这几个字段就是刚才我们在视图里添加的 ...
现在我们在请求使用 Drupal 的视图创建的这个电影资源列表的时候,有个问题。就是这个 field_poster 属性,它的值是一个带 img 标签的电影海报图像 ... 在我们的 React Native 项目里,只需要得到电影海报图像的地址就行了 ..
因为我们不能在 React Native 里面,使用 img 这个标签去显示图像,而是用的 Image 这个组件 ... 我们需要给这个组件提供一个要显示的图像的地址 .. 所以这里需要再去处理一下这个 field_poster 字段输出的内容 ..
最简单的方法是去安装一个叫 image_url_formatter 的模块 ..
我们可以在命令行下面使用 drush 去安装一下这个模块 .. 进入到 drupal 项目所在的目录 .. 先去下载一下这个模块 .. 输入 drush dl image_url_formatter -y
成功以后再去启用一下这个模块 .. drush en image_url_formatter -y
完成以后,再回到 drupal 的后台 .. 在这个 REST export 视图显示里面,再去配置一下这个电影海报图像字段 ..
安装了 image_url_formatter 模块以后,在这个图像字段的格式化器里面,会多出一个 image url,选择它 ... URL 类型选择 Full URL .. 图像样式仍然是 中号海报 .. 应用一下这个配置 .. 再保存一下这个视图 ..
回到 POSTMAN ,重新请求一下这个地址 ... 这次返回来的数据里面,这个 field_poster 属性的值就变成了一个图像的地址 ...
现在我们得到的数据列表里已经有几个可以显示的项目了,title ,field_release_date,field_poster,还有 field_name ... 下面把这些东西添加到列表项目里面去显示。
打开 MovieList ,在 renderMovieList 这个方法里返回的就是每个列表项目的显示 .. 之前我们注释掉了一些不想使用的东西.. 下面重新再设计一下 ...
这个 Image 组件里要显示的就是电影的海报 .. 在它的 source 属性里,uri 属性对应的值就是海报图像的地址 .. 在这里可以使用 movie.field_poster 来表示 ..
保存 ... 模拟器上会出现一个错误的提示 .. 说不能把 field_poster 的值解释成一个正确的图像地址 .. 这很可能是 image_url_formatter 模块的一个 bug ..
回到 POSTMAN .. 再看一下这个字段的值 .. 你会发现,这个图像地址的前面,有两个空格 .. 结尾的地方还有一个换行符 .. 这很可能是引起错误的原因 .. 再回到编辑器 ..
这里我们可以去掉 field_poster 值里面的空格还有换行符 .. 用一个 replace 方法 .. 要替换的东西用一个正则表达式 ..它可以匹配换行符还有空格 ... 替换成没东西 ...
replace(/(\r\n|\n|\r| )/gm, '')
再保存一下 .. 这次就会正常显示这个海报字段里的图像了 ...
在这个 itemMeta 里面,前面这块之前显示的是电影的原名 .. 在我们请求回来的数据里,这个电影的原名是在 field_name 这个属性里 ... movie.field_name ..
后面是电影的发行年代 .. 它是在 field_release_date 里面 .. movie.field_release_date ..
下面原本还有一个电影的评分 .. 不过现在 Drupal 8 不没有合适的评分模块 .. 以后有机会再介绍一下 .. 先保存一下 ..
你会看到,在这个电影列表的每个项目里面,都会显示出我们设计好的一些字段 ...
现在这里只会显示三个项目 .. 因为我们限制了每页输出的项目的数量 .. 回到 Drupal 的视图配置界面 .. 在分页器里,重新设置一下每一页内容要显示的项目的数量 .. 现在是 3 .. 这里我们把它设置成 10 .. 应用 .. 再保存一下 ..
回到 iOS 模拟器 .. command + R .. 刷新一下页面的显示 ... 现在一次会显示 10 个项目 ..
再简单回顾一下使用 ListView 组件的时候分页功能的设计,这个列表视图组件在滚动到列表底部的时候会执行 onEndReached 属性指定的动作,这里就是 onEndReached 这个方法 ..
在这个方法里, 我们去执行了一个 loadMore 去载入页面的新的内容,在这个 loadMore 里面,使用了 fetch 去请求下一页内容上的内容资源 .. 然后把这些内容合并到当前在页面上显示的内容里面 ... 我们在这里又设置了一下,下一次要请求的地址 .. 这样用户再次浏览到列表底部的时候 ... 可以把新的页面上的内容载入到当前页面上显示出来 ..
下面我们要根据 Drupal 返回的内容资源,修改一下这个无限载入的分页功能 ...
我们先给组件添加一个表示当前页码的状态 .. 名字可以是 page .. 它的默认的值设置成 0 .. 因为 Drupal 的分页的页码是从 0 开始的,也就是第一页的页码是 0 ... 第二页是 1 ...
这里的 count 状态表示的是每一页要显示的列表项目的数量 .. 把它设置成 10 ... 因为在 Drupal 视图的分页器设置里,我们让每一页显示 10 个项目 ..
start ,还有 total 这两个状态是豆瓣 API 上特有的东西,我们可以去掉它们 ..
再去重新设置一下请求的地址 .. 找到 requestURL 这个方法 .. 它是返回请求地址用的一个方法 .. 这里添加一个 page 参数 .. 这是 Drupal 分页要求用的一个参数 .. 它的值就是一个要显示的页码, 它的值先用一个 page ..
给这个方法添加一个参数 .. 名字是 page .. 默认的值是组件里的 page 这个状态,就是刚才我们添加的那个状态 ..
再找到 fetchData 方法 .. 它是组件初始的时候要请求数据用的一个方法 .. 在这里,我们可以去设置一下 page 这个状态 .. 它的值是当前 page 这个状态再加上 1 .. 意思就是下一次请求的时候,就会往后翻一页 ..
找到 onEndReached .. 浏览到列表底部的时候会执行这个方法,它里面先判断了一个条件,然后决定是不是要执行 loadMore .. 可以先去掉这个要判断的条件 ..
再找到 loadMore .. 它可以去请求新页面上的内容,然后把新的内容放到当前页面上显示出来 .. 先去掉这个 newStart 变量... 设置的状态这里,也去掉这个 start 状态 .. 这些东西是我们在使用豆瓣 API 的时候要用到的东西 ..
这里再添加一个要设置的状态 .. 名字是 page ,它的值就是让当前的页码加上一个 1 .. 这样下一次执行这个方法的时候,会去请求新页面上的内容 ..
注意现在这个列表里里,最后一个项目是 心灵捕手 ..
保存一下 .. 现在推荐电影这个页面上默认会显示第一页内容,也就是 10 个电影项目 .. 再向下滚动这个页面 .. 出现了一个错误 .. 这是因为在把新内容放到当前页面上显示的时候遇到的一个错误 .. 这里新页面上的内容直接就是 responseData .. 去掉 subjects 这个属性 ..
再保存一下 .. 回到模拟器 .. 向下滚动列表 ..
到底儿的时候,会去请求下一页上的内容,然后把这些内容放到当前页面上再显示出来 ..
在这个列表视图里,我们用了一个 renderFooter 方法,指定了一下显示页脚的方法,就是这个 renderFooter, 在这个方法里面, 我们判断了一下,如果还有要显示的内容,就在页脚上显示一个加载指示 .. 如果没有内容了,就提示用户已经没有可以显示了内容了 ..
下面再根据 Drupal 返回的内容,改造一下这个页脚 .. 可以再去添加一个新的状态 .. 名字是 noResult .. 用它表示是否还有要显示的内容 .. 默认的值是 false ..
再找到 loadMore .. 在这里我们可以去判断一下,如果请求回来的结果是一个空白的数组 .. 我们就去把组件的 noResult 状态的值设置成 true ,表示已经没有要显示的内容了 ..
用一个 if .. 判断一下 .. responseData.length .. ,它的值是不是等于 0 .. 如果是 .. 就去设置一下组件的状态 .. 要设置的是 noResult .. 把它的值设置成 true ..
再找到 renderFooter 这个方法 .. 现在我们就可以根据组件的 noResult 这个状态,来决定到底是显示一个正在加载的指示,还是显示一个没有结果的提示 ..
判断的条件是 !this.state.noResult ..
保存一下 .. 到模拟器上再试一下 .. 向下滚动页面 .. 因为还有需要显示的内容,所以会显示一个正在加载的指示 .. 继续滚动 .. 没有内容了,就会显示一个没有内容的提示 ...
在每个要显示的项目的上面,我们用了一个 TouchableHighlight 组件 .. 用户按下项目的时候,会执行它的 onPress 属性指定的动作 .. 这里用的是 showMovieDetail ..
这个方法会把用户带到一个新的页面上,页面的标题就是要显示的电影的标题,使用的组件是 MovieDetail .. 它还会给 MovieDetail 传递一个属性,属性的值是 movie 这个参数 .. 这个 movie,里面包含的就是每个电影项目 .. 电影标题,名字,海报之类的东西 ..
再打开 MovieDetail 这个组件 .. 在 app/Components 的下面 .. 找到这个 MovieDetail.js ..
在这个组件里,我们要去请求要显示的这个电影内容 .. 再把想要的东西显示到页面上 ..
然后打开 结构 .. 视图 .. 找到我们自己创建的这个 REST 视图 .. 编辑一下 .. 在这个视图显示的字段里,添加一个内容 id 的字段,因为在显示单个内容的时候,我们要使用内容的 id 号去请求一下这个内容 ..
找到 节点id .. 勾选一下 .. 应用 .. 再保存一下 .. 然后打开 POSTMAN ,再去请求一下这个 api/movie ... 你会看到,现在返回的内容里面,每个项目里都会有一个新的属性 .. 名字是 nid .. 这个 nid 就是节点内容的 id 号 ..
想要得到某个具体的节点内容,需要用到这个 id 号 .. 比如想要得到 id 号是 xx 的这个内容 .. 请求的地址是 node/xx .. 加上一个 _format 参数,设置一下数据的格式 .. hal_json ..
再添加一个头部信息 .. 名字是 Accept .. 值是 application/hal+json .. 再发送一下这个请求 ..
下面返回的就是 id 号是 xx 的内容 ..
13)显示单个内容 - 实施打开 MovieDetail.js .. 在个组件的功能就是去显示单个的内容。 先修改一下请求的地址 ... 网站的基本的地址 .. 加上 /node/ .. 后面是节点内容的 id 号 .. 这里可以使用 this.props.movie.nid 来表示 .. movie 这个属性里的值是从列表视图那里传递过来的 .. 它里面的 nid 就是节点内容的 id 号 ..
后面再加上一个 ?_format 参数 .. 值是 hal_json ...
fetchData 这个方法会去请求这个地址 .. 然后把请求回来的结果放到组件的 movieDetail 这个状态里面 .. 又把 loaded 这个状态的值设置成了 true ,表示已经载入了内容 ..
我们给它里面用的这个 fetch ,再添加一个参数 .. 是一个对象 .. 里面用一个 headers .. 它的值又是一个对象 .. 在这个对象里,可以设置请求的头部信息 ..
添加一个 Accept .. 对应的值是 application/hal+json .. 设置一下接收的内容的格式 ...
在组件的 render 方法里面,我们暂时只用到了电影内容的正文 .. 这个内容的值是在 body 这个属性里面 .. 回到 POSTMAN 看一下 .. 找到 body 这个属性 ..
注意这个属性的值是一个数组 .. 数组里面是对象 .. 这个对象里的 value 属性的值就是电影内容的正文 ..
回到编辑器 .. 这个 summary 变量组织了正文内容 .. 修改一下 .. movie.body[0].value ...
后面用了一个 split 方法,它会根据内容里的换行符,把内容分成几部分,我们在每一部分内容上面都用了一个 View 包装了一个 Text ,这样可以在这些内容之间添加一些间隔 ..
Drupal 正文里的换行符是 \r\n\r\n ..
再保存一下这个文件 .. 找到一个电影项目 .. 按一下它 .. 这样会把用户带到这个电影内容的详细页面上 .. 在这个页面上现在只会显示出电影内容的正文 .. 也就是 body 字段的值 .. 你也可以在这里显示其它的东西,找到对应的属性,或者根据某个属性的值去请求新的内容,然后使用 React Native 的 View 还有 Text 组件组织一下,再添加点样式就行了 ..