Vue中关于响应式的一个问题

vue

最近在参加一个面试,对方发了一套面试题过来;要求是做一个类似京东生鲜的网站,要求实现商品列表功能;之前我一直都是在vue-cli脚手架中使用vue;由于这个页面比较少,所以直接引入的CDN但是却发现不能进行v-for渲染了。下面是我的错误代码

<!DOCTYPE html>

<html>

    <body> 

            <div id="link-tab"  >

                <div class="tab-list" v-for="item in goodsdata">

                    <a class="goods-show">

                        <div class="goods-pic">

                            <img v-bind:src="item.imgurl" alt="fruit-picture"/>

                        </div>

                        <div class="goods-info">

                            <div class="goods-title">{{item.title}}</div>

                            <div class="goods-price">

                                <div class="price">

                                    <span>¥{{item.price}}</span>

                                </div>

                                <div class="sale-price">

                                    <span>¥{{item.salePrice}}</span>

                                </div>

                            </div>

                            <div class="goods-evalution">

                                <span class="evalute-num">{{item.evaluteNum}}条评价</span>

                                <span class="good-precent">好评{{item.goodsPrecent}}</span>

                            </div>

                        </div>

                    </a>

                </div>

            </div>

        </div>

        <script type="application/javascript" src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

        <script type="application/javascript" src="http://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>

        <script type="application/javascript">

            document.addEventListener("DOMContentLoaded", getTabList);

            var _this = this;

            var tab = new Vue({

                el:'#link-tab',

                data:{

                    goodsdata:[]

                }

            });

            function getTabList() {

                $.ajax({

                    type:"get",

                    url:"http://localhost:3000",

                    async:true,

                    success:function(res){

                        res = JSON.parse(res);

                        console.log(res.code);

                        if(res.code == 1){

                              _this.goodsdata = res.data ;

                              console.log(_this.goodsdata);

                        }else{

                            console.log("request ERROR");

                        }

                        

                    }

                });

            }

        </script>

    </body>

</html>

页面一直没有渲染出结果,我的goodsdata里面是有数据的。如图:

我的流程是在页面加载的时候发送ajax请求获取数据;填充tablist,数据虽然获取到了,但是页面一直没有被填充。到这里我首先开始寻找原因,我想是不是我的Ajax请求发送的时候有问题;因为Ajax请求需要时间来进行请求和响应。而我监听的是DOM加载完毕之后触发Ajax请求拿数据。这样有可能导致的问题是我的界面中所有的DOM节点加载完毕,DOM树构建完成;而我初始化的goodsdata数据为空,后面的ajax请求拿到的数据是在DOM构建完成之后才拿到的;所以DOM树在第一次构建的时候不会渲染v-for所在的元素,因为里面的数据为空。

  既然这样的话,那我是否可以在页面的DOM树加载之前就触发Ajax请求;这样就可以在DOM树构建之前拿到数据从而确保Vue能够进行正确的渲染。关于页面生命周期的介绍https://www.jianshu.com/p/3b581af02ebf  后来我了解到readystatechange事件,我想通过在loading地方做判断来执行ajax请求;但是似乎页面的readystatechage事件触发的时候,readyState属性的值就已经改变为interactive ;因此这条路似乎走不通。而根据我查询到的事件触发的顺序来说DOMContentLoaded事件的触发已经算得上是最开始的事件了,而且由于ajax请求是异步请求;在等待响应期间DOM会继续解析和渲染。因此等待在DOM进行渲染之前加载Ajax请求似乎可行性不大。

  既然这条路走不通,那我就想到Vue的响应式。即数据发生改变时会动态的渲染DOM,于是我将代码进行了如下修改

 var _this = this;

           var goods= {goodsdata:[]};

           document.addEventListener('DOMContentLoaded',getInfo());

           var tab = new Vue({

               el:'#link-tab',

               data:_this.goods,

           })

           function getInfo(){

               $.ajax({

                   type:"get",

                   url:"http://localhost:3000",

                   async:true,

                   success:function(res){

                       res = JSON.parse(res);//将JSON字符串序列化为JSON对象

                       if(res.code == 1){

                           _this.goods.goodsdata = res.data;

                           console.log(_this.goods.goodsdata);

                       }

                       else{

                       console.log("request ERROR")

                       }

                   }

               });

           }

我将this的指向提前声明给_this,然后创建了一个和Vue实例中data对象相同的对象goods;并将其加入到了data对象中;于是效果出现了。需要说明的只有data中的对象才会被响应。

而在Vue.js文档中是这么说的:当一个 Vue 实例被创建时,它向 Vue 的响应式系统中加入了其 data 对象中能找到的所有的属性。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值

 原因是因为goods对象被加入到了Vue实例的data对象中,我改变了goods对象的值;由于Vue响应式的特点,这个值的改变被进行了追踪。所以DOM重新进行了渲染,

经过尝试我还发现下面这种方法也可以实现如上的效果:究其原因是因为我在created钩子函数部分执行了ajax请求,改变了data对象中goodsdata的值。所以Vue追踪到这个变化响应式的重新进行了渲染

var tab = new Vue({

                el:'#link-tab',

                data:{

                    goodsdata:[]

                },

                created:function({

                    var _this = this;

                    $.ajax({

                    type:"get",

                    url:"http://localhost:3000",

                    async:true,

                    success:function(res){

                        res = JSON.parse(res);

                        if(res.code == 1){

                              _this.goodsdata = res.data ;

                              console.log(_this.goodsdata);

                        }else{

                            console.log("request ERROR");

                        }

                        

                    }

                });

                })

            });

至此这个问题总算是解决了,但是关于为何只有data中的对象是被响应的;响应式的原理又是什么,我将在下面几篇文章中继续深入的去探究这个问题

以上是 Vue中关于响应式的一个问题 的全部内容, 来源链接: utcz.com/z/378084.html

回到顶部