【问题标题】:sort/filter content with javascript使用 javascript 对内容进行排序/过滤
【发布时间】:2018-08-21 14:55:57
【问题描述】:

简介

我为我的一个朋友编写了一个投资组合网站作为大学项目。 我开始学习 Vue.js 并开始深入研究 JavaScript。

http://janpzimmermann.com

在某些情况下,我仍在为所有新事物而苦苦挣扎。因此,我将 Vue.js 与 jQuery 和 JavaScript 混合使用。我知道这不是最佳做法。 但是在我花了很多年的时间主要是 html 和 css(有时还有一点 PHP)之后,有些东西对我来说仍然是新的。 ;)

问题

我创建了一个画廊网格(内容是通过 Vue 加载的)并且希望能够通过导航过滤内容。 因此,我遇到了以下方法: https://www.w3schools.com/howto/howto_js_filter_elements.asp

    /* content filter */
filterSelection("all");

function filterSelection(c) {
  var x, i;
  x = document.getElementsByClassName("content-filter");
  if (c == "all") c = "";
  // Add the "view" class (display:block) to the filtered elements, and remove the "view" class from the elements that are not selected
  for (i = 0; i < x.length; i++) {
    w3RemoveClass(x[i], "view");
    if (x[i].className.indexOf(c) > -1) w3AddClass(x[i], "view");
  }
}

// Show filtered elements
function w3AddClass(element, name) {
  var i, arr1, arr2;
  arr1 = element.className.split(" ");
  arr2 = name.split(" ");
  for (i = 0; i < arr2.length; i++) {
    if (arr1.indexOf(arr2[i]) == -1) {
      element.className += " " + arr2[i];
    }
  }
}

// Hide elements that are not selected
function w3RemoveClass(element, name) {
  var i, arr1, arr2;
  arr1 = element.className.split(" ");
  arr2 = name.split(" ");
  for (i = 0; i < arr2.length; i++) {
    while (arr1.indexOf(arr2[i]) > -1) {
      arr1.splice(arr1.indexOf(arr2[i]), 1);
    }
  }
  element.className = arr1.join(" ");
}

不幸的是,似乎有一个错误。 当我打开一个项目时,不要使用关闭按钮关闭它并导航到一个新类别并在那里打开一个项目,之前打开的项目会再次添加到 DOM 中(即使它不属于该类别!)。

我也找不到错误。我也无法确定这不是 Vue 的错。

但我尝试用 jQuery 过滤器替换 JavaScript 过滤器(这个过滤器与数据属性一起使用),遗憾的是这对我不起作用。因为我只能为每个项目添加一个属性。但有时一个项目属于多个类别。 (这个:https://jsfiddle.net/k5g6wcw3/21/

    // Variable
var posts = $('.post');
posts.hide();


// Click function
$( ".sort" ).click(function() { 
    // Get data of category
    var customType = $( this ).data('filter'); // category
    console.log(customType);
    console.log(posts.length); // Length of articles

    posts
        .hide()
        .filter(function () {
            return $(this).data('cat') === customType;
        })
        .show();
});

// All
$( "#showAll" ).click(function() {
  $( ".post" ).show();
});

进一步的想法

我知道这也应该与 vue 路由和 vuex 相关,但找不到我可以理解的方法。

谢谢

【问题讨论】:

标签: javascript jquery vue.js


【解决方案1】:

像这样混合使用 Vue 和 jQuery 会让事情变得比他们需要的要困难很多很多,很多。您在使用第一个过滤器时遇到的问题是因为 Vue 不知道您的 javascript 过滤器正在执行的 DOM 修改,因此在下次更新时覆盖了它们。如果你让 jQuery 过滤器正常工作,你将会遇到完全相同的问题。

所以不要那样做。

现在你让 Vue 绘制一个完整的项目列表,然后在添加数据属性并隐藏你想要过滤掉的元素之后尝试爬取 DOM。这是很多额外的工作(对于您和浏览器而言),并且每当 Vue 进行重绘时都会失败(因为它会破坏您在外部所做的更改。)

相反,将属性放入您提供给 Vue 的数据中,并让 Vue 在绘制 DOM 之前对其进行过滤。这是pretty simple to do in Vue

(您曾提到每个项目需要多个类别;这是一个计算属性的快速示例:

data: {
    currentFilter: 'photo',  // set this from a route param, or a v-model, or whatever
    projects: [
        {name: "Project one", categories: ['photo', 'book']},
        {name: "Project two", categories: ['website']},
        {name: "Project 3", categories: ['photo']}
        // ...
    ]
},
computed: {
   filteredProjects() {
      return this.projects.filter(project => {
          return project.categories.indexOf(this.currentFilter) > -1
      })
   }
}

让您的模板 v-for 超过 filteredProjects 而不是 projects,您就完成了。每当data.currentFilter 更改时,列表将自动重绘,并按新值过滤。)

可能在 Vue 中使用 jQuery,但它需要很好地理解框架在做什么,这样你就不会在它和你的外部代码之间产生冲突。 (而且我还没有发现将 jQuery 的东西重写为 Vue 组件并不简单。)其他现代框架如 React 或 Angular 也是如此。这些都在一个非常不同的模型上工作,而不是 jQuery 倾向于依赖的 DOM 优先策略。尤其是在学习时,如果您一次只坚持一个框架,而不是试图将它们混合在一起,那么您将获得更轻松的时间。

【讨论】:

  • 很遗憾我不能给你一个赞成票,但我真的很感谢你的回答。示例代码等内容清晰详细。非常感谢。我会尝试植入你建议的东西!
  • 感谢您的客气话——很高兴我能帮上忙!
  • 还有一个问题。如何将 currentFilter 设置为全部显示,例如在起始页上?
  • 有很多不同的方法可以做到这一点;一种可能是如果 currentFilter 设置为空字符串,则计算属性只返回原始数组,否则返回过滤后的数组。
猜你喜欢
  • 2021-01-19
  • 1970-01-01
  • 2016-05-17
  • 2011-01-24
  • 2010-09-21
  • 1970-01-01
  • 2017-06-19
  • 2019-11-04
  • 2021-05-29
相关资源
最近更新 更多