本文写于:2021-4-6。1.原因今??天在写一个小组件的时候,发现第一次挂载时,通过父组件传递给子组件的props的值是可以正常获取的。超过价值。二、问题一、问题描述:我要实现的是父组件通过props给子组件传值。父子组件如下:子组件是一个评论点赞的小组件,也就是下图中蓝色区域的组件。由于这个小组件需要在多个地方使用,所以封装成一个小组件。父组件是外面的整个区域。但是这个widget请求的数据只有在挂载的时候是正确的,其他时候是错误的,也就是点击分类的时候获取不到数据,因为这个widget需要从父组件获取文章id然后去数据库中获取一些点赞数和评论数,但是奇怪的是第一次获取文章id是正常的,但是第二次获取不到,所以无法更新尝试:分类按钮如下:(这个是实时分类区:可以看到这个分类的第一篇文章点赞数和评论数分别是1和3,此时是正常的数据采集)但是当我切换分类的时候:(可以看到此时评论和点赞的数量没有变化,对于本题来说合理正确的值都是0,而且因为我的处理,如果点赞和评论都为0,则数字不会可以显示,但是这里还是显示1、3)2、请教一个问题:为什么第一次挂载父组件不显示?传入的数据是正确的,然后切换类别时的数据请求是错误的?3、问题分析:我想了想,发现一个普通的父组件在给子组件的props传递组件时,应该是这样的:挂载时:(1)挂载时是否请求数据,或者当创建时请求数据,这个父组件运行到挂载的生命周期时,此时已经获取到数据。(2)然后父组件现在挂载并传递给子组件的props。这个时候数据是正常的,因为父组件的dom元素创建完成后,此时子组件的dom元素已经创建完成。比如父组件相当于刚出生的婴儿,子组件相当于器官。在婴儿出生之前,里面的器官(子成分)会逐渐形成。当所有的器官都创建完成后,宝宝就可以出生了(由父组件创建完成)。(3)此时父组件诞生后,会将获取的数据传递给子组件。子组件被正常获取。挂载后:(1)挂载后,在获取到父组件请求的数据之前:此时,每点击一个分类,父组件就会重新请求一组数据,此时,由于父组件已经诞生,子组件已经创建,所以当父组件请求网络数据还没有取到值时,子组件的数据已经有值了。这些值是挂载时传递给子组件的数据,所以直接使用子组件。(2)mount后,获取到父组件请求的数据后:父组件获取到新的数据,会传递给子组件,但是props传递给子组件时,子组件的视图层已经渲染好了,虽然此时props中的数据会再次发生变化,但是view层中的数据仍然是父组件挂载时传给他的数据,不会响应式的变化,从而导致报错.4.解决问题:由于我们的props其实是可以接收到父组件的,所以我们只要在子组件中实时监听相应的props变化,然后根据变化做出相应的动作,就可以完成子组件的什么-组件正在努力实现。更新?所以解决代码:watch:{topic_id(newValue,oldValue){this.topic_id=newValue;console.log("新值:",newValue);//异步处理,由于父组件mainbox是一个异步进程,所以需要watch这个变量,一旦变量发生变化,重新发送请求计算总评论数gettotal_agree_comment_reply(this.topic_type,this.topic_id).then((res)=>{this.totalAgrees=res[0].totalAgrees;Assignthis.totalcp=res[0].totalComment_Reply;//评论和回复总数/??/console.log("评论和点赞总数:",水库);});},},然后切换类别,正常请求数据。注意:本场景的父子组件是通过道具分类的场景,即父组件的数据会变化多次,而不是只变化一次。还有类似于分类的分页场景,但是我统一称之为父组件数据动态变化的场景,比如这个场景,需要监听props的数据变化。5.后记:本来想用computed的,因为vue官方一直在推荐用computed来代替watch,但是我觉得这种情况好像不会触发computed:因为vue官方下面有这么一段话:据说只有当响应式数据发生变化时,计算属性才会实时变化,但是如果数据不是响应式的,那么它就不会发生变化。关于响应式数据的详细讲解,可以访问官网:Vue响应式原理,我这里还是做一个简单的记录。vue中什么类型的数据是响应式的:当你将一个普通的JavaScript对象作为数据选项传递给Vue实例时,Vue会遍历这个对象的所有属性,并使用Object.defineProperty将所有这些属性转换为getter/setter。Object.defineProperty是ES5中无法shimmed的特性,这也是Vue不支持IE8及以下浏览器的原因。这些getters/setters对用户是不可见的,但在内部它们允许Vue跟踪依赖项并在访问和修改属性时通知更改。这里需要注意的是,不同的浏览器在控制台打印数据对象时getter/setter的格式不同,所以建议安装vue-devtools以获得更友好的用户界面来查看数据。每个组件实例对应一个watcher实例,watcher实例会在组件渲染过程中记录“touched”数据属性作为依赖。然后,当依赖项的设置器触发时,观察者会收到通知,从而导致其关联的组件重新呈现。对于对象,Vue无法检测属性的添加或删除。由于Vue在初始化实例时会对属性进行getter/setter转换,因此该属性必须存在于数据对象上,Vue才能将其转换为响应式。例如:varvm=newVue({data:{a:1}})//`vm.a`是响应式的vm.b=2//`vm.b`是非响应式的。:通读一遍,主要告诉vue的使用者:(1)对于每一个创建的组件,vue都会开启一个自定义的内部functionwatcher来实现其响应式。(2)Vue响应式数据是data.data中定义的变量。如果你在数据之外定义一个变量,它是没有响应的。所以我们通过props传递给子组件的值并不是data中的数据,是不响应式的,而computed是依赖响应式的。即使props中的数据发生变化,computed仍然无法检测到,所以这里只能使用watch。完全的。
