VueJS $观看$ refs

时间:2016-08-19 09:23:30

标签: javascript vue.js

是否可以OpenText Vue Element content = doc.getElementById("content"); Elements links = content.getElementsByTag("a"); for (Element link : links) { String linkHref = link.attr("href"); String linkText = link.text(); }

我想针对嵌套在当前Vue实例中但在Elements links = doc.select("table a[href]"); 回调内部的子组件设置逻辑,$watch在处理时最初是$refs

ready

$refs.childcomponent

结果:错误:超出最大调用堆栈

实例的

undefined属性

ready()

结果:没有。

6 个答案:

答案 0 :(得分:13)

您可以$watch $refs.<name>.<data>但不能$refs.<name>本身,更不用说$refs

https://jsfiddle.net/kenberkeley/9pn1uqam/

const Counter = {
  data: () => ({
    i: 0
  }),
  template: `<fieldset>
    <p>Counter</p>
    <code>i = {{ i }}</code>
    <button @click="i += 1"> Add One </button>
  </fieldset>`
}

const App = {
  components: { Counter },
  mounted () {
    this.$watch(
        () => {
            return this.$refs.counter.i
        },
      (val) => {
        alert('App $watch $refs.counter.i: ' + val)
      }
    )
  },
  template: `<fieldset>
    <p>App</p>
    <counter ref="counter" />
  </fieldset>`
}

new Vue({
    el: '#app',
    render: h => h(App)
})

答案 1 :(得分:8)

不,$ refs不是被动的,手表不起作用。

答案 2 :(得分:2)

在下面的已安装使用代码中:

names_and_values = {
    "WebDriverConfig.maximize_browser" : "true",
    "WebDriverConfig.reset_per_iteration": "true",
    # ...
}

for name, value in names_and_values.items():
    element = next(root.iterfind(f'.//*[@name="{name}"]'))
    element.text = value

print(ET.tostring(root)) 

答案 3 :(得分:0)

对此有一个解决方法。考虑到JavaScript在将数组分配给变量时不会创建数组的副本,而只是创建对原始数组的引用。知道Vue的$ refs是数组,我们可以执行以下操作:

<template>
    <div>
            <ul v-if="showAvailable">
                 <li v-for="pet in allPets.available" :key="pet.id" ref="pets">
                      {{ pet.name }}
                 </li>
            </ul>
            <ul v-else>
                 <li v-for="pet in allPets.unavailable" :key="pet.id" ref="pets">
                      {{ pet.name }}
                 </li>
            </ul>
    </div>
</template>

<script>

export default {
    props: ['allPets'],

    data() {
         showAvailable: true // Normally would change from a button or something
         shownPets: null // set to null for now
    },

    mounted() {
         this.$set(this.$data, 'shownPets', this.$refs.pets);    
    },

    watch: {
         shownPets: {
                         handler(newVal, oldVal){
                              // Do something when the DOM changes!
                         },
                         deep: true
                    }
    }
}
</script>

瞧瞧。组件安装后,我们将数据shownPets设置为宠物$ref。根据{{​​1}}是showAvailable还是true,引用将包含不同的元素,现在我们可以监视$ ref或DOM的变化。

答案 4 :(得分:0)

以下解决方案使用 MutationObserver

在安装的钩子中添加:

const config = {
      attributes: true,
      childList: true,
      subtree: true
    };
 // this will be triggered for any change in your element
    this.observer = new MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        if (mutation) {
          this.infoHeight = this.$refs.info.clientHeight + 'px'
          console.log(" changed ", this.$refs.info.clientHeight)
        }
      });
    });
//observe the referenced element
    this.observer.observe(this.$refs.info, config);

完整示例

Vue.config.devtools = false;
Vue.config.productionTip = false;

new Vue({
  el: '#app',
  data: () => ({
    infoHeight: 0,
    observer: null,

    img: "https://images.ctfassets.net/hrltx12pl8hq/6TOyJZTDnuutGpSMYcFlfZ/4dfab047c1d94bbefb0f9325c54e08a2/01-nature_668593321.jpg?fit=fill&w=480&h=270"

  }),
  mounted() {
    const config = {
      attributes: true,
      childList: true,
      subtree: true
    };
    this.observer = new MutationObserver((mutations) => {
      mutations.forEach((mutation) => {
        if (mutation) {
          this.infoHeight = this.$refs.info.clientHeight + 'px'
          console.log(" changed ", this.$refs.info.clientHeight)
        }
      });
    });
    this.observer.observe(this.$refs.info, config);


  },

 beforeDestroy(){
   this.observer.disconnect()
  },
  methods: {
    changeImg() {
      this.img = "https://i.pinimg.com/originals/a7/3d/6e/a73d6e4ac85c6a822841e449b24c78e1.jpg"
    },

  }
})
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>


<div id="app" class="container">
  <p>{{infoHeight}}</p>

  <button class="btn btn-primary" @click="changeImg">Change image</button>
  <div ref="info">
    <img :src="img" alt="image" />
  </div>
</div>

答案 5 :(得分:0)

如果您在 created() 期间在 $refs 中定义属性,或者如果您不需要数据中的后备存储,则在 beforeCreate() 期间定义属性,这是可能的。例如:

const vm = new Vue({
    el: "#app",
  data() {
    return {
        mode: 0,
        refTest: undefined
    };
  },
  created() {
    Object.defineProperty(this.$refs, 'test', {
      get: function () {
        return this.refTest;
      }.bind(this),
      set: function (newValue) {
        console.log(`set - Setting test refs to an array? ${Array.isArray(newValue)}`);
        this.refTest = newValue;
      }.bind(this),
      enumerable: true
    });
  },
  watch: {
    refTest: {
      handler(newValue, oldValue) {
        console.log(`watch - array? ${newValue ? Array.isArray(newValue) : undefined}`);
      },
      deep: false,
      immediate: true
    }
  },
  methods: {
    toggle() {
        this.mode = (this.mode === 1) ? 2 : 1
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <button @click="toggle">Toggle</button>
  <ul v-if="mode === 1">
    <li ref="test">Single Ref</li>
  </ul>
  <ul v-else-if="mode === 2">
    <li ref="test" v-for="s in ['Multiple', 'Refs']" :key="s">{{ s }}</li>
  </ul>
  <div v-else>No Refs</div>
</div>

这是我尝试过的唯一解决方案,当参考没有与组件本身一起安装时。

这里使用defineProperty的原因是因为如果ref发生变化,观察者将失去对它的跟踪。

如果您想在defineProperty 中处理您的操作,我想这没问题,然后您就可以摆脱您的观察者了。但是你总是需要一个后备存储——尽管它不需要在数据中。