资讯专栏INFORMATION COLUMN

React学习笔记2:React官方CommentBox实践

VPointer / 1850人阅读

摘要:浏览器看效果效果显示效果就是瞎比比我不听瞎比比解析后的文本直接被显示在页面上,并没有被浏览器解析,这是为了防止被攻击而作的保护措施。

新搭建的个人博客,本文地址:React学习笔记2:React官方CommentBox实践
所有的操作是继续上一个学习笔记,参考的是React官方的CommentBox,不过不是100%按照其实现。
参考:https://facebook.github.io/re...

1、首先创建相关的文件

touch src/comment.js

2、修改webpack配置,一处是告诉webpack预处理的实体增加comment.js,另外一个是告诉webpack输出的时候按照文件名字编译输出,而不是将所有js文件编译到bundle.js,[name]实际上是entry数组中的key,通过修改key可以归类目录,例如"comment/index":./src/index.js,"comment/index":"./src/comment.js"会将编译后的文件放到comment目录下,通过这些配置可以更好的组织代码结构

  entry:{
    "index":"./src/index.js",
    "comment":"./src/comment.js"
  },
  output: {
     path: path.resolve(__dirname, "build"),
     filename: "[name].js"
  },

3、修改"build/index.html"引入文件修改为comment.js,重新运行webpack-dev-server,开始修改comment.js

4、分拆Comment组件,梳理出如下结构,在React中所有的东西都是以组件的形式存在

- CommentBox
  - CommentList
    - Comment
  - CommentForm

5、创建CommentBox组件,return()中的类html内容,在react中叫做JSX语法,其本身符合XML语法,react在编译后会转化为相应的js文件,官方介绍https://facebook.github.io/re...
之后可以去浏览器中看下效果

var CommentBox = React.createClass({
  render:function(){
    return (
      
Hello world! I am a comment box.
) } }); //渲染组件,注意修改index.html中div的id为content ReactDOM.render( ,document.getElementById("content") );

6、创建CommentList、CommentForm组件

var CommentList = React.createClass({
  render:function(){
    return (
      
Hello, I am a comment list!
) } }); var CommentForm = React.createClass({ render:function(){ return (
hi, I am a comment form.
) } });

7、修改CommentBox代码,引入CommentList、CommentForm组件。下面代码中混合了HTML和组件代码,JSX编译器会自动将HTML代码用React.createElement(tagName)去转换。浏览器看下效果。

var CommentBox = React.createClass({
  render:function(){
    return (
      

Comments

) } });

8、创建Comment组件,里面有{this.props.author}和{this.props.children}两个变量,称之为组件的属性。修改CommentList组件,可以看到我们传递了author属性。children是React预置属性,指向组件内嵌的内容。返回浏览器查看修改变化。

var Comment = React.createClass({
  render:function(){
    return (
      

{this.props.author}

{this.props.children}
) } }) //修改CommentList组件,让其载入Comment组件 var CommentList = React.createClass({ render:function(){ return (
就是瞎比比 我不听瞎比比
) } });

9、添加Markdown支持

//安装依赖包
npm install marked --save
//引入marked包
var marked = require("marked")
//修改Comment组件,利用marked组件解析评论内容,转为富文本格式。使用toString()是为了明确传送给marked的为字符串格式。浏览器看效果效果
var Comment = React.createClass({
  render:function(){
    return (
      

{this.props.author}

{marked(this.props.children.toString())}
) } })
//显示效果
Comments
stone

就是瞎比比

mpanda

我不听瞎比比

hi, I am a comment form.

10、解析后的文本直接被显示在页面上,并没有被浏览器解析,这是react为了防止被XSS攻击而作的保护措施。React提供了一个并不友好的特殊API保证能够实现在浏览器显示原始HTML

var Comment = React.createClass({
  rawMarkup:function(){
    var rawMarkup = marked(this.props.children.toString(),{sanitize:true})
    return {__html:rawMarkup}
  },
  render:function(){
    return (
      

{this.props.author}

) } })

JSX中dangerouslySetInnerHTML属性必须在接收到一个对象参数,且对象参数中明确使用__html作为key时,才会将其内容作为原始HTML插入页面中,而且不建议直接在

直接这样完成书写,目的就是明确提醒开发者,这里是有风险的,您是绝对的信任这段插入的内容。再次查看浏览器效果。It works!
11、评论数据显然应该来自服务器,不过在动态获取之前,我们先模拟一些数据

var data = [
  {"id":1,"author":"stone","text":"换一个位置瞎比比"},
  {"id":2,"author":"mpanda","text":"不喜欢你瞎比比"},
]
//传递数据到CommentBox
ReactDOM.render(
  ,document.getElementById("content")
);
//直接传递数据到CommentList
var CommentBox = React.createClass({
  render:function(){
    return (
      

Comments

) } }); //在CommentList重新完成组件的组装,刷新浏览器看效果 var CommentList = React.createClass({ render:function(){ var commentNodes = this.props.data.map(function(comment){ return ( {comment.text} ) }); return (
{commentNodes}
) } });

12、从组件封装来说我们已经封装了一个很不错的组件,只需要传递相关json数据到CommentBox即可。不过所有的数据都是在组件创建的时候,利用不可变量参数props一次性传递给组件。state同样为组件的私有变量,可以通过this.setState()来设置变量的值,每次设置变量的值,组件都会重新渲染一遍自己。利用state修改我们的程序,让其动态渲染页面。

//为了方便进行ajax请求,引入jquery,当然完全可以不引入
var $ = require("jquery")
var CommentBox = React.createClass({
  //getInitialState函数在组件的整个生命周期只会执行一次,我们在里面初始化数据
  getInitialState:function(){
    return {data:[]}
  },
  //componentDidMount函数同样是有React自动调用,时间是在组件第一渲染完毕后。当然因为data在初始化的时候数据为空,实际上这时候渲染的组件没有内容。
  componentDidMount:function(){
    $.ajax({
      url:this.props.url,
      //因我本地server是php,且跨域,所以我们使用jsonp解决跨域问题,具体jsonp实现,请自行google
      dataType:"jsonp",
      cache:false,
      jsonp:"callback",
      jsonpCallback:"getComment",
      success:function(data){
        //获取到数据后,通过setState设置数据,组件会自动再次渲染
        this.setState({"data":data})
      }.bind(this),
      error:function(xhr,status,err){
        console.log(this.props.url,status,err.toString())
      }.bind(this)
    })
  },
  render:function(){
    return (
      

Comments

) } }); //将URL地址传递个组件 ReactDOM.render( ,document.getElementById("content") );

13、我们在浏览器看效果的时候因为数据请求都是在毫秒级别完成不方便看到重新渲染的效果,我们引入一个定时器。刷新浏览器,哈哈,2s后自动载入了评论数据。

var CommentBox = React.createClass({
  getInitialState:function(){
    return {data:[]}
  },
  loadCommentsFromServer:function(){
    $.ajax({
      url:this.props.url,
      dataType:"jsonp",
      cache:false,
      jsonp:"callback",
      jsonpCallback:"getComment",
      success:function(data){
        this.setState({"data":data})
      }.bind(this),
      error:function(xhr,status,err){
        console.log(this.props.url,status,err.toString())
      }.bind(this)
    })
  },
  componentDidMount:function(){
    setInterval(this.loadCommentsFromServer,2000)
  },
  render:function(){
    return (
      

Comments

) } });

14、官方教程中评论提交分两种完成。第一种完成了提交完成后,需要刷新,再次从服务器获取评论数据,第二种提交评论后直接把提交的数据附加到评论后面,利用setState重新渲染页面。显然第二种体验更好,直接实现第二种。
先做分析,在CommentForm组件中,如果完成数据的提交,那么需要重新设置CommentList中的数据,但是CommentList的数据又是CommentBox传递过去的,那么提交数据的操作不如直接在CommentBox中完成,然后利用setState重新设置CommentList的数据,CommentList完成自动刷新。

//之前获取评论接口利用的是jsonp,但是提交评论必须post方法,所以jsonp无法完成,但是有不能通过跨域操作。webpack支持proxy(代理)模式,可以把一部分接口直接转发到后端,修改webpack配置,请自行替换后端服务。
    devServer:{
        contentBase:"./build",
        proxy:{
            "/api/*":{
                target:"http://***.local.com:80",
                host:"***.local.com",
                secure: false,
            },
            bypass: function(req, res, proxyOptions) {
                if (req.headers.accept.indexOf("html") !== -1) {
                    console.log("Skipping proxy for browser request.");
                    return "/index.html";
                }
            },
        }
    }
//注意传递的url,会自动转发到http://***.local.com:80/api/comment
ReactDOM.render(
  ,document.getElementById("content")
);
var CommentBox = React.createClass({
  //增加评论提交方法,后台服务  
  handleSubmitComment:function(data){
    $.ajax({
      //请注意,后台接口我把评论和获取评论放到了一起,只是提交方式不一样,一个是get,一个是post
      url:this.props.url,
      type:"POST",
      data:data,
      dataType:"json",
      cache:false,
      success:function(data){
        //测试接口直接返回了我提交的内容,所以可以直接附加数据,让CommentList自动刷新
        this.setState({data:this.state.data.concat(data)});
      }.bind(this),
      error:function(xhr,status,err){
        console.log(this.props.url,status,err.toString())
      }.bind(this)
    })
  },
  render:function(){
    return (
      

Comments

//将评论提交接口传递个CommentForm组件
) } }); var CommentForm = React.createClass({ getInitialState:function() { return {author:"",text:""} }, //完成数据的绑定,通过setState也能保证跟此数据相关的UI完成重新的渲染 handleAuthorChange:function(event){ this.setState({author:event.target.value}) }, handleTextChange:function(event){ this.setState({text:event.target.value}) }, handleSubmit:function(event){ //组织表单默认的submit提交 event.preventDefault(); var author = this.state.author.trim() var text = this.state.text.trim() if(!text||!author) { return; } //调用CommentBox上的评论提交方法 this.props.onSubmitComment({author:author,text:text}); this.setState({author:"",text:""}) }, render:function(){ return (
) } });

到此整个示例联系完成!之后要完成用es6语法重构该项目。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/78554.html

相关文章

  • React学习笔记3:用es2015(ES6)重写CommentBox

    摘要:新搭建的个人博客,本文地址学习笔记用重写在一开始的时候配置中我们就加入了的支持,就是下面的配置,但之前的学习笔记都使用的完成,所以专门作一篇笔记,记录使用完成创建相关文件修改,增加该入口文件修改,引入该文件做个简单的测试,看下浏览器全部用来 新搭建的个人博客,本文地址:React学习笔记3:用es2015(ES6)重写CommentBox在一开始的时候webpack配置中我们就加入了e...

    selfimpr 评论0 收藏0
  • 学习React系列1-React-tutorial全解析

    摘要:例子全解析近些时间一直在关注,关于如何学习可以参照链接的文章自行制定计划。千里之行,始于足下。此外,输出的内容要解析为,而在默认情况下,基于预防攻击的考虑,对输出的内容是不解析为的。 React-tutorial例子全解析 Talk is cheap,Show me the code 近些时间一直在关注React,关于如何学习React可以参照链接的文章自行制定计划。千里之行,始于足下...

    SnaiLiu 评论0 收藏0
  • react组件通信实现表单提交

    摘要:组件通信实现表单提交昨晚做了一个的例子,主要实现的是提交表单实现评论的功能,在做之前先简单介绍一下。并称为前端大框架,就目前来看,尽管发布了也在今年月份发布了,更不在话下,大家要是想学习的话可以去官网学习。 react组件通信实现表单提交 昨晚做了一个react的例子,主要实现的是提交表单实现评论的功能,在做之前先简单介绍一下React。 showImg(https://segment...

    LoftySoul 评论0 收藏0
  • 翻译 | React AJAX最佳实践

    摘要:作者沪江前端开发工程师本文原创翻译,有不当的地方欢迎指出。管理数据,而提供服务器上的数据,因此应用于处理网络请求。结论使用建立的应用都是模块化的会成为其中一个模块,库是另一个模块。原文原创新书移动前端高效开发实战已在亚马逊京东当当开售。 作者:Oral (沪江Web前端开发工程师)本文原创翻译,有不当的地方欢迎指出。转载请指明出处。 当你问起有关AJAX与React时,老司机们首先就会...

    DirtyMind 评论0 收藏0
  • React表单

    摘要:从服务端请求数据创建一个文件大胖分钟前天气不错啊骚胖分钟前出去玩啊老胖分钟前去哪玩啊从服务端请求数据为了页面的数据和服务端的保持联系,设置每隔五秒向服务端发生一次请求在帮顶一下事件提交表单。。。。 React表单 首先,我们需要搭建一个React环境,用来实现效果: 先安装React,这里我用的并不是最新版本的,所以需要选择一个版本: jspm install react@0.14.0...

    Coding01 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<