Django+React全栈开发:文章列表

React

如今咱们有了一个属于文章的API,能够添加、修改、删除、查看文章,可是对于咱们的网站来讲,还须要一个用户界面才行。如今开始探索一下ReactJS吧。css

常常听到有前端三大框架Angular、React、Vue的说法,不过React官网对本身的介绍倒是这样的:html

A JavaScript library for building user interfaces

一个用来构建用户界面的JavaScript库。首先咱们须要配置一下环境,以便使用React前端

首先咱们要安装一个Node.js,目前咱们还不用深刻了解Node,只须要知道它能帮助你在非浏览器环境下运行JS代码就好了。官网为node.org,直接下载安装就行,Linux用户推荐用各自的包管理器安装。node

Node自带包管理器npm,有点相似Python的pip,不过这里咱们使用yarn这个包管理器。按照官网说明安装完以后,打开终端,并进入咱们的项目目录react_drf,为接下来的工做作准备。react

从零开始构建一个React项目涉及到的东西是比较多的,这时候就有一些方便的脚手架能够选择,脚手架能够帮咱们省掉不少麻烦的配置。在这里先选用Facebook官方提供的create-react-appnpm

$ yarn create react-app frontend

使用上述命令后,你将会看到react_drf目录下多了个frontend文件夹:编程

$ cd frontend
$ yarn start

这下你会看到浏览器跳转到localhost:3000,而且应该看到一个转动的React logo的页面,这说明你安装成功了,接下来浏览一下frontend这个目录下的文件,但还不要作任何改动。json

index.js

如今让咱们一块儿来看一下frontend/src这个目录,基本上目前咱们只要关心这个目录下的内容就能够了。首先来看一下这里的frontend/src/index.js后端

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

可能你已经注意到了代码中的<App />这一部分,彷佛HTML中并无这一标签,而且为何JS文件中有这样相似HTML的东西呢?可能你的心中已经布满了疑问,不要紧,让咱们先动手改一下这段代码:浏览器

...
<React.StrictMode>
    <div>hello world</div>
  </React.StrictMode>,
...

我想,上述写法应该能让你看出应该在哪里修改代码。如今,打开浏览器,看看localhost:3000这个页面,应该能看到页面发生了改变并显示了hello world。若是你以前不当心关闭了终端,请记得从新打开,并在frontend目录下运行yarn start

这里我不打算详细介绍React的基础知识了,目前我尚未见过比React官方文档更好的学习资料,哪怕你以为本身的英语不好劲,官方的中文文档也值得一看,这里我仅仅粗略介绍一下接下来要接触的知识点。

  • JSX:不够恰当但简单理解的话,能够认为在React中能够把HTMLCSSJavaScript混合在一块儿,一个本来在HTML中的元素能够被赋值给变量,如const element = <h1>Hello, world!</h1>;JSX里面也能够插入JS,如
const name = 'Josh Perez';
// 使用JS变量
const element = <h1>Hello, {name}</h1>;
  • 组件:能够简单理解为,React认为UI应该是组件化的,就像搭积木同样,由一个一个组件搭起来,这样将一个大页面的工做拆分为不少个小组件,便于复用,也方便多人协做开发。以前看到的<App />就是一个组件。
  • 生命周期函数:有一个有趣的比喻,把组件比做一只蚂蚁,它的一辈子就是从一根绳子的一端爬向另外一端,这个绳子上挂了不少卡片,那么它从头爬到尾,就会在过程当中触碰到不一样的卡片,这些卡片就是生命周期函数

第一个组件

frontend/src目录下建立新文件ArticleList.js,正如名字所示,这是一个文章列表的组件。

import React, {Component} from "react";

class ArticleList extends Component {
  constructor(props) {
    super(props);
  }

}

如今咱们定义了一个类组件,它继承自ReactComponent类,这里咱们写了它的第一个生命周期函数,也就是constructor,若是你熟悉过任何一门面向对象的语言,这里应该不难理解。constructor并非React独有的,而是JavaScript原生的写法,不过对于类组件来讲,它固然也能够算生命周期的一部分。

如今来看第二个生命周期函数render

class ArticleList extends Component {
  constructor(props) {
    ......
  }

  render() {
    return <div>第一个组件</div>;
  }

}

render函数是类组件中惟一一个必须被实现的函数,组件将根据这个函数的返回值渲染内容。这里的<div>第一个组件</div>就是JSX,若是有多行嵌套能够用括号括起来:

return (
      <div className="ArticleList">
        <div>文章一</div>
        <div>文章二</div>
      </div>
    );

那怎么让这个组件被渲染呢?聪明的你可能已经把App.js的代码看了一遍,咱们在ArticleList.js的最后面添加一行代码

export default ArticleList;

同时修改index.js

import React from 'react';
......
// 原先引入App的那行能够删掉
import ArticleList from './ArticleList'

ReactDOM.render(
  <React.StrictMode>
    <ArticleList />
  </React.StrictMode>,
  document.getElementById('root')
);

......

如今运行yarn start,你将在看到浏览器启动并显示你在render函数中返回的内容。固然事实上若是你以前没有中止终端的运行,那么就没必要要从新运行yarn start,代码作了更改,会自动从新渲染,之后再也不提醒如何查看咱们的成果了。

接下来开始实现文章列表界面,可是先不急着从API获取文章数据,先让咱们模拟一下文章数据:

const articleList = [
  {
    "id": 2,
    "title": "React",
    "body": "React is good",
    "created": "2020-03-21T21:19:31.732703",
    "updated": "2020-03-21T21:19:31.732728"
  },
  {
    "id": 1,
    "title": "React",
    "body": "React is good",
    "created": "2020-03-21T21:10:53.922033",
    "updated": "2020-03-21T21:10:53.922128"
  }
];

class ArticleList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      articleList: articleList,
    }
  }
  ......
}

注意到这里添加了一个articleList列表,在构造函数里多了一个this.state,并为其设置了articleList属性。如今来修改render函数:

render() {
    return (
      <div className="ArticleList">
        {this.state.articleList.map(item =>
          <div key={item.id}>
            <h4>{item.title}</h4>
            <p>
              <strong>{item.body}</strong>
              <br/>
              <em>建立时间:{item.created}</em>
              <em>更新时间:{item.updated}</em>
            </p>
          </div>
        )}
      </div>
    );
  }

如今来大体讲解一下上面的代码,首先咱们看到最外层的div标签,它拥有一个className属性,这个实际上就是HTMLclass属性,这么写的缘由也很简单,JSX容许JSHTML混合在一块儿,但在不少编程语言(包括JS)里class都是用于建立类的关键字,因此给它改个名字便于区分。

接着咱们看到了在JSX中如何使用JavaScript,咱们在大括号里使用了map方法,使用箭头函数,让不一样标签里包含了文章标题、正文等内容。

注意到包含<div key={item.id}>这一行,如今若是你已经使用了yarn start命令,你将会在浏览器看到一个简陋的文章列表,若是你删除这个key={item.id},在浏览器按下F12,你将会在控制台看到警告信息。

FBI Warning

总之记住React要求这类列表元素,必需要要有一个惟一的key标识来让React识别哪些元素被改变了。在后台的真实数据中,id这个字段是主键,也就是惟一的,恰好能够利用。

使用API

好了,咱们已经使用虚假的数据尝试了一把,以前说过先后端分离开发的一个好处是前端与后端约定好接口后,能够各自分开并行开发,那么实质上就会有一些工具来帮助生成“假的API”或者虚假的前端请求之类来帮助测试,有兴趣的能够去搜索搜索。

固然这里咱们是为了学习,开发只有本身一我的而已,那如今让咱们来试试使用真实的API吧。

同源策略

在正式开始以前,咱们还要先了解一下浏览器的同源策略。想象一下,若是你在a.com登陆浏览了一段时间,再跑去b.com逛逛,结果b.com直接取到了你在a.comcookie,用于在a.com登陆你的帐号,那实在是太可怕了,尤为是当a.com是银行或购物网站的时候。基于此,浏览器使用同源策略来作一个基本的安全保障。简单来讲,就是域名、端口、协议只要有一个不同,就会受到访问限制:

  • Cookie、LocalStorage 和 IndexDB 没法读取。
  • DOM 没法得到。
  • AJAX 请求不能发送。

咱们能够简单尝试一下,修改ArticleList.js

constructor(props) {
    ......
  }

  componentDidMount() {
    fetch('http://127.0.0.1:8000/articles/')
      .then(response => response.json())
      .then(result => this.setState({articleList: result}))
      .catch(e => e);
  }
  ......

这里咱们又见到了一个新的生命周期函数componentDidMount将在render以后执行。这里调用了原生的fetch函数,直接简单粗暴的请求API,在浏览器中按下F12,你会看到以下报错:

报错

虽然域名(IP)、协议都相同,可是端口号却不一样Django后台在8000React却在3000,因此发生了错误。

这里给出一个在开发时能够用的方案,帮助咱们解决这个问题,固然,在实际部署时不能这么作,部署时的具体状况之后再讲,这里咱们先找到frontend/package.json这个文件,在其中添加一行:

{
 .......,
 "proxy": "http://127.0.0.1:8000"
}

省略号表明以前的内容,若是你插入在文件最后面可别忘了给前面加一个逗号。

接着对源代码作一处修改:

componentDidMount() {
    fetch('/articles/')
      ......
  }

这样开发服务器就能识别你的请求将其代理到http://127.0.0.1:8000也就是Django服务所在的地址了,如今从新运行yarn start,能够在浏览器看到你在后端添加的数据啦。

效果图

结语

此次就讲到这里了,下一章要讲讲将此次的代码在细节上优化一下。这一章有不少React的基础知识并无讲解,若是读者对React目前尚未一点了解,那么建议如今去React官网看一下,至少把基础教程看完。


欢迎关注个人公众号“公子政的宅平常”,原创技术文章第一时间推送。

myqr.gif

相关文章
相关标签/搜索