简体   繁体   English

使用 vue.js 和 axios 操作注入的 HTML

[英]Manipulating injected HTML using vue.js and axios

I'm writing a page with vue.js and axios to grab the content of the newest post from a category of a WP site by means of REST API.我正在使用 vue.js 和 axios 编写一个页面,以通过 REST API 从 WP 站点的类别中获取最新帖子的内容。 The post content is always an ordered list (OL).帖子内容始终是有序列表 (OL)。 The items of the injected OL will then be displayed as a carousel.注入的 OL 的项目随后将显示为轮播。 The OL is injected successfully, but fail to be manipulated. OL注入成功,但操作失败。 Is there anyone would kindly point out the problem in the JS I wrote?有没有人会指出我写的JS中的问题? The same task can be done easily using jQuery, but I just want to practice something new.使用 jQuery 可以轻松完成相同的任务,但我只是想练习一些新的东西。

HTML: HTML:

<div class="frame ajax annoucements">
  <h1 id="announcements-title" class="material ajax-title">Announcements<span class="title-this-week"></span></h1>
  <div id="app" class="ajax-body material" v-html="posts[0].content.rendered">
  </div>
</div>

JS: JS:

var tcnt = 0;

new Vue({
  el: '#app',
  data: {
    posts: []
  },
  created() {
    axios.get('http://www.just-a-wp-site.com/wp-json/wp/v2/categories/')
    .then((response) => {
      var categoryId = 0;
      response.data.forEach(function(category){
        if (category.slug == 'announcements') {
          categoryId = category.id;
          console.log('Category ID: ' + category.id);
        }
      });
      return categoryId;
    })
    .then((categoryId) => {
      console.log(categoryId);
      return axios.get('http://www.just-a-wp-site.com/wp-json/wp/v2/posts/', {
        params: {
          categories: categoryId,
          per_page: 1,
          status: 'publish'
        }
      });
    })
    .then((response) => {
      console.log(response.data);
      this.posts = response.data;
    })
    .catch((error) => {
      console.log(error.message);
    })
  },
  mounted() {
    var announcements = document.querySelectorAll('frame.ajax .ajax-body > ol > li');
    console.log(announcements.length);
    setInterval(function(){
      var target = announcements.length % tcnt;
      for (i = 0; i < announcements.length; i++) {
        if (i == target) {
          announcements[i].style.display = 'block';
        }
        else {
          announcements[i].style.display = 'initial';
        }
      }
      tcnt++;
    }, 1000);
  }
});

It's a timing issue.这是一个时间问题。

You will need to understand the asynchronous nature of Javascript./您将需要了解 Javascript 的异步特性。/

When you do document.querySelectorAll('frame.ajax .ajax-body > ol > li') in mounted hook, the ajax request probably hasn't responded yet.当您在挂载钩子中执行document.querySelectorAll('frame.ajax .ajax-body > ol > li')时,ajax 请求可能尚未响应。 Therefore, the DOM elements do not exist yet and it does not work as expected.因此, DOM 元素还不存在,并且无法按预期工作。

My suggestion is to put the codes for DOM manipulation into a method and call it after the ajax request has responded.我的建议是将 DOM 操作的代码放入一个方法中,并在 ajax 请求响应后调用它。

See listManipulation method:listManipulation方法:

var tcnt = 0;

new Vue({
    el: '#app',
    data: {
        posts: []
    },
    created() {
        axios.get('http://www.just-a-wp-site.com/wp-json/wp/v2/categories/')
            .then((response) => {
                var categoryId = 0;
                response.data.forEach(function(category) {
                    if (category.slug == 'announcements') {
                        categoryId = category.id;
                        console.log('Category ID: ' + category.id);
                    }
                });
                return categoryId;
            })
            .then((categoryId) => {
                console.log(categoryId);
                return axios.get('http://www.just-a-wp-site.com/wp-json/wp/v2/posts/', {
                    params: {
                        categories: categoryId,
                        per_page: 1,
                        status: 'publish'
                    }
                });
            })
            .then((response) => {
                console.log(response.data);
                this.posts = response.data;
                this.$nextTick(() => {
                    this.listManipulation();
                })
            })
            .catch((error) => {
                console.log(error.message);
            })
    },
    methods: {
        listManipulation() {
            var announcements = document.querySelectorAll('frame.ajax .ajax-body > ol > li');
            console.log(announcements.length);
            setInterval(function() {
                var target = announcements.length % tcnt;
                for (i = 0; i < announcements.length; i++) {
                    if (i == target) {
                        announcements[i].style.display = 'block';
                    } else {
                        announcements[i].style.display = 'initial';
                    }
                }
                tcnt++;
            }, 1000);
        }
    }
});

$nextTick means wait for the DOM to update first, then executes the code inside. $nextTick表示先等待 DOM 更新,然后执行里面的代码。


It's also considered bad practice to manipulate DOM directly in a Vue project.在 Vue 项目中直接操作 DOM 也被认为是不好的做法。 Because Vue keeps track of the DOM changes using Virtual DOM.因为 Vue 使用 Virtual DOM 来跟踪 DOM 的变化。 If you modify the DOM, Vue won't keep track of that and may overwrite the modification the next time it updates.如果你修改了 DOM,Vue 将不会跟踪它,并且可能会在下次更新时覆盖修改。

Since you are controlling the display, you should check out v-if由于您正在控制显示器,因此您应该检查v-if

give you an example for carousel,without jQuery and any DOM operations:给你一个轮播的例子,没有 jQuery 和任何 DOM 操作:

 var app = new Vue({ el: '#app', data() { return { list: [1,2,3,4], curIndex: 0 } }, created () { window.setInterval(_=>{ if(this.curIndex+1>this.list.length-1){ this.curIndex = 0; }else{ this.curIndex++ } },3000) } })
 .wrapper{ width: 200px; height: 100px; position: relative; } .wrapper>div{ position: absolute; left: 0; top: 0; width: 100%; height: 100px; line-height: 100px; text-align: center; color: #fff; } .wrapper>div:nth-child(1){ background: red; } .wrapper>div:nth-child(2){ background: blue; } .wrapper>div:nth-child(3){ background: orange; } .wrapper>div:nth-child(4){ background: yellow; } .fade-enter,.fade-leave-active{ opacity: 0; } .fade-enter-active,.fade-leave-active{ transition: opacity .5s ease-in-out; }
 <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <div id="app"> <transition-group tag="div" class="wrapper" name="fade"> <div v-for="(item,index) of list" :key="index" v-show="index==curIndex"> {{item}} </div> </transition-group> </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM