jsonp react 获取返回值_Django+React全栈开发:文章列表

7a8bc501dc1c6304020c1270142a0261.png

React

现在我们有了一个属于文章的API,可以添加、修改、删除、查看文章,但是对于我们的网站来说,还需要一个用户界面才行。现在开始探索一下ReactJS吧。

经常听到有前端三大框架Angular、React、Vue的说法,不过React官网对自己的介绍却是这样的:

A JavaScript library for building user interfaces

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

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

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

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

$ yarn create react-app frontend

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

$ cd frontend
$ yarn start

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

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,你将会在控制台看到警告信息。

1b2861a2fc4a0227663faa7dd4e960dd.png

总之记住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,你会看到如下报错:

bc23d612f6c085428aa469d40684ac8c.png

虽然域名(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,可以在浏览器看到你在后端添加的数据啦。

1d11fc44c2ef45a9a58c5cecfaab2bbd.png

结语

这次就讲到这里了,下一章要讲讲将这次的代码在细节上优化一下。这一章有很多React的基础知识并没有讲解,如果读者对React目前还没有一点了解,那么建议现在去React官网看一下,至少把基础教程看完。


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

95c1f9f5b93857afeaa2451635134140.png

D

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/556493.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

24个经典的MySQL索引问题,你都遇到过哪些?

1、什么是索引&#xff1f; 索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分)&#xff0c;它们包含着对数据表里所有记录的引用指针。 索引是一种数据结构。数据库索引&#xff0c;是数据库管理系统中一个排序的数据结构&#xff0c;以协助快速查询、更新数…

java 3 4_Java-3/4_树.md at master · yrcDream/Java-3 · GitHub

树二叉树二叉树具有唯一根节点二叉树每个节点最多有两个孩子&#xff0c;最多有一个父亲二叉树具有天然递归结构二叉树不一定是 “满” 的&#xff1a;一个节点也是二叉树、空节点也是二叉树二叉搜索树(BST)BST 的基本功能public class BST> {private Node root;private int…

python模块导入_python模块导入

不同的执行方式&#xff1a; 从IDE中执行&#xff0c;python程序由IDE设置环境决定。 从系统中执行&#xff0c;python程序由环境变量中的系统变量path决定&#xff0c;从上往下选择。 模块导入顺序&#xff1a; 系统包优先级最高 > 同目录 > sys.path&#xff0c;之所以…

再也不怕SVN冲突:轻松解决SVN冲突

什么时候容易出现冲突&#xff1f; 多个人同时修改了同个文件中的同一行代码 无法进行对比的二进制文件&#xff0c;比如图片等 如何解决冲突&#xff1f; 如上图&#xff0c;test_conflict.py文件发生了冲突&#xff0c;并且多出了几个文件&#xff0c;其中.mine是我本地修…

手机型号大全_2020值得入手的三款手机。每个优秀,选择哪一个?励志故事名言视频...

如今&#xff0c;手机等数码产品更新很快。各种新的技能&#xff0c;让用户真正体验到科技的力量&#xff0c;它可以被描述为“具有多种功能的一个装置。”然而&#xff0c;这么多车型&#xff0c;难免有些人不知道如何选择。当4G和5G手机**的对峙&#xff0c;很多朋友也问小中…

AspectJ

Aspectj与Spring AOP比较 XML配置方式 <aop:aspect>&#xff1a; 定义切面, 包括通知和切点. 是一般的bean//定义切面 public class SleepHelperAspect{public void beforeSleep(){System.out.println("睡觉前要脱衣服&#xff01;");}public void afterSleep…

aixs1 生成java代码_通过axis1.4 来生成java客户端代码

1.首先下载axis-1.4所有的jar包&#xff0c;2.我是直接打开cmd&#xff0c;进入到该jar包的目录下&#xff0c;3.直接运行命令(运行这个命令之前要确定java的环境变量都已配置好)&#xff1a;java -Djava.ext.dirs${lib的目录} org.apache.axis.wsdl.WSDL2Java -o${代码输出路径…

windows分屏_windows内到底藏了多少好东西?

恭喜!点开这篇文章&#xff0c;你将解锁 WIN10 系统内那些不为人知的高效的冷知识&#xff01;相信所有的职场人都会搜索过这样的问题&#xff1a;有哪些高效的办公神器&#xff1f;在之前的文章中&#xff0c;我分享过很多高效神器&#xff0c;如果你感兴趣的话&#xff0c;点…

@Aspect中@Pointcut 12种用法

本文主要内容&#xff1a;掌握Pointcut的12种用法。 Aop相关阅读 阅读本文之前&#xff0c;需要先掌握下面3篇文章内容&#xff0c;不然会比较吃力。 Spring系列第15篇&#xff1a;代理详解&#xff08;java动态代理&CGLIB代理)Spring系列第30篇&#xff1a;jdk动态代理…

asp.net接受表单验证格式后再提交数据_看滴普科技大前端如何玩转el-form-renderer 表单渲染器1.14.0

DEEPEXI 大前端常人道&#xff0c;一入开发深似海&#xff0c;技术学习无止境。在新技术层出不穷的前端开发领域&#xff0c;有一群身怀绝技的开发&#xff0c;他们在钻研前沿技术的同时&#xff0c;也不忘分享他们的成果&#xff0c;回馈社区。下面&#xff0c;就由小水滴带大…

测试用例设计方法_黑盒测试——测试用例设计方法

黑盒测试也称为功能测试或数据驱动测试。通过软件的外部表现来发现其缺陷和错误。在测试时&#xff0c;把被测程序视为一个不能打开的盒子&#xff0c;在完全不考虑程序内部逻辑结构和内部特性的情况下进行。它是在已知产品所应具有的功能前提下&#xff0c;通过测试来检测每个…

SpringAop @Pointcut(“@annotation“)\@Aspect练习

切面记录日志 切面类 Slf4j Aspect Component public class AspectForFeign {Pointcut("execution(public * com.keke.remote..*Feign.*(..))")public void pointcut() {}Around("pointcut()")public Object around(ProceedingJoinPoint joinPoint) thro…

Mybatis缓存机制详解与实例分析

前言&#xff1a; 本篇文章主要讲解Mybatis缓存机制的知识。该专栏比较适合刚入坑Java的小白以及准备秋招的大佬阅读。 如果文章有什么需要改进的地方欢迎大佬提出&#xff0c;对大佬有帮助希望可以支持下哦~ 小威在此先感谢各位小伙伴儿了&#x1f601; 以下正文开始 Mybat…

delphi语言转为汇编语言_每天5分钟,轻松建立技术图谱 编程语言黑历史

阿T课堂开播啦&#xff01;这里只有干货干锅&#xff0c;没有水坑没有套路&#xff01;计算机编程语言的发展&#xff0c;也是随着计算机本身发展而发展。人类不断的提高科技的同时&#xff0c;也必须使工具的使用越来越简化&#xff0c;从而提高整个社会效率&#xff0c;这其中…

水系图一般在哪里找得到_进展 | 水系钠离子电池研究取得重要进展

水系钠离子电池兼具钠资源储量丰富和水系电解液本质安全的双重优势被视为一种理想的大规模静态储能技术。此前&#xff0c;我们针对这水系钠离子电池体系做了一些探索(Nature Communications 2015, 6, 6401&#xff1b;Advanced Energy Materials 2015, 5, 1501005&#xff1b;…

@Around简单使用示例——SpringAOP增强处理

Around的作用 既可以在目标方法之前织入增强动作&#xff0c;也可以在执行目标方法之后织入增强动作&#xff1b;可以决定目标方法在什么时候执行&#xff0c;如何执行&#xff0c;甚至可以完全阻止目标目标方法的执行&#xff1b;可以改变执行目标方法的参数值&#xff0c;也…

python numpy逆_Python使用numpy计算矩阵特征值、特征向量与逆矩阵

原标题&#xff1a;Python使用numpy计算矩阵特征值、特征向量与逆矩阵 Python扩展库numpy.linalg的eig()函数可以用来计算矩阵的特征值与特征向量&#xff0c;而numpy.linalg.inv()函数用来计算可逆矩阵的逆矩阵。 >>> importnumpy as np >>> x np.matrix([…

Mysql索引数据结构有多个选择,为什么一定要是B+树呢?_面试 (MySQL 索引为啥要选择 B+ 树)

Mysql索引数据结构 下面列举了常见的数据结构 二叉树红黑树Hash表B-Tree&#xff08;B树&#xff09; Select * from t where t.col5我们在执行一条查询的Sql语句时候&#xff0c;在数据量比较大又不加索引的情况下&#xff0c;逐行查询并进行比对&#xff0c;每次需要从磁盘…

一篇搞懂mysql中的索引(大白话版)

容易来说&#xff0c;索引的出现其实就是为了提升数据查询的效率&#xff0c;就像书的目录一样。一本 500 页的书&#xff0c;如果你想快速找到其中的某一个知识点&#xff0c;在不借助目录的情况下&#xff0c;那我估计你可得找一会儿。同样&#xff0c;对于数据库的表而言&am…

sqlite插入时间字段_sqlite 获取最后插入id

(点击上方公众号&#xff0c;可快速关注)SQLite数据库中的表均有一个特殊的rowid字段&#xff0c;它是一个不重复的64位有符号整数&#xff0c;默认起始值为1。rowid别名为oid或_rowid_&#xff0c;但在创建表的SQL声明语句中只能使用rowid作为关键字。如果在创建表的时候设置了…