Vue.js对象代理:道具未显示在Object.keys

时间:2018-08-21 18:56:41

标签: javascript vue.js

Vue.js代理其对象以捕获属性访问。我似乎在抽象中发现了一个漏洞:Object.keys不在键列表中返回道具。

具有以下Vue组件:

function callMe() {
  var comp = Vue.component("comp", {
    template: "<button @click='clickMe()'>xxx</button>",
    props: {
        label: String,
        cardId: String,
        collapsible: {
            type: Boolean,
            default: true,
        },
        collapsed: Boolean,
    },
    data() {
        console.log(Object.keys(this))
        console.log(this.collapsible)
        console.log(Object.keys(this).includes("collapsible"))
        return { isCollapsed: this.collapsed }
    },
    methods: {
       clickMe(){
         console.log(this)
       } 
    }

  })
  var vm = new Vue({
    el: '#root',
    template: "<comp></comp>",
  })
}
callMe();
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.11/dist/vue.js"></script>
<div id='root'>
 
 <button @click="clickMe()" >Click Me</button>

</div>

控制台输出为:

(29) ["_uid", "_isVue", "$options", "_renderProxy", "_self", "$parent", "$root", "$children", "$refs", "_watcher", "_inactive", "_directInactive", "_isMounted", "_isDestroyed", "_isBeingDestroyed", "_events", "_hasHookEvent", "_vnode", "_staticTrees", "$vnode", "$slots", "$scopedSlots", "_c", "$createElement", "$attrs", "$listeners", "_watchers", "_props", "toggleThis"]
true
false

(有趣的是,当我稍后致电支票时,isCollapsed项目在列表中。您还会注意到,还存在clickMe方法。似乎只保留了道具。 )

为什么会这样?

更笼统地说,Vue的Proxy对象如何发出与之后无法访问的密钥集不同的密钥?

这对我来说是个问题,因为我正在尝试使用pug-vdom进行某些操作,并且在内部使用Object.keys枚举要注入Pug模板的变量。

这是Vue的错误吗? 或者,是否可以从this对象访问道具键列表,并导出一个也包含道具的对象?

编辑:添加了一个可运行的代码段,以演示该问题。

1 个答案:

答案 0 :(得分:1)

Object.keys()不会迭代原型属性。
子组件也是来自根组件的inherited。 这意味着道具和数据字段必须在子组件的__proto__内。

因此,如果我们执行Object.keys(this__proto__).includes("collapsible"),它将在子组件中返回true

如果要从子组件访问这些字段,请使用this.$propsthis.$data

function callMe() {
  var comp = Vue.component("comp", {
    template: "<button @click='clickMe()'>xxx</button>",
    props: {
        label: String,
        cardId: String,
        collapsible: {
            type: Boolean,
            default: true,
        },
        collapsed: Boolean,
    },
    data() {
        console.log('Inside Child:',Object.keys(this))
        console.log(this.collapsible)
        console.log(Object.keys(this.__proto__).includes("collapsible"))
        console.log(Object.keys(this).includes("collapsible"))
        return { isCollapsed: this.collapsed }
    },
    methods: {
       clickMe(){
         console.log(this)
       } 
    }

  })
  var vm = new Vue({
    el: '#root',
    template: "<comp></comp>",
    props:{
    jack:{
          type: Boolean,
          default: true
         }
    },
    data(){
      console.log('Inside parent:', this.jack)
      return {}
    }
  })
}
callMe();
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.11/dist/vue.js"></script>
<div id='root'>
 
 <button @click="clickMe()" >Click Me</button>

</div>