2 фильтра на массив в 1 функции VUE JS

119
25 декабря 2019, 08:50

Хотела на массив повесить 2 фильтра. Логика такая: 1 - фильтр для поиска. При вводе названия, массив "перерисовывается" и обратно.
2 - при клике на чекбокс, массив также фильтруется, в зависимости от того, какое у чекбокса значение: true или false. (если true, то объект массива в основном списке пропадает и отрисовывается в списке "просмотренные")

Обе функции (для фильтрации при "поиске" и для фильтрации в основном списке и отрисовке в новом) у меня уже есть. (функция для фильтрации в зависимости от true/false прописана в закомменченном коде в той же функции с первым фильтром) Каждая по отдельности правильно работает. НО Я не знаю, как мне 2 эти функции соединить в одну.

Занимаюсь 3 недели в целом, на вью около 2 недель. Не судите строго пожалуйста

new Vue({ 
    el: '#app', 
    data: { 
        movies: [ 
            { 
                'film': "Мстители, 2012", 
                'seen': false, 
                'id': 1 
            }, 
            { 
                'film': "Первому игроку приготовиться, 2018", 
                'seen': false, 
                'id': 2 
            }, 
            { 
                'film': "Аватар, 2009", 
                'seen': false, 
                'id': 3 
            }, 
            { 
                'film': "Волк с УолСтрит, 2013", 
                'seen': false, 
                'id': 4 
            }, 
            { 
                'film': "Аквамен, 2018", 
                'seen': false, 
                'id': 5 
            }, 
            { 
                'film': "Джон Уик, 2014", 
                'seen': false, 
                'id': 6 
            }, 
            { 
                'film': "Прибытие, 2016", 
                'seen': true, 
                'id': 7 
            } 
        ], 
        search: '' 
     }, 
    
    computed:{ 
    //отфильтровать массив при поиске 
      filteredMovies: function() { 
        let filtered = this.movies; 
            if (this.search) { 
                filtered = this.movies.filter( 
                m => m.film.toLowerCase().indexOf(this.search) > -1); 
            } 
        return filtered; 
         
    //отфильтровать текущий массив и отрисовать в новом массиве 
        // return this.movies.filter(function(movie) { 
        //     return !movie.seen; 
        //   }) 
 
      }, 
      watched: function() { 
        return this.movies.filter(function(movie) { 
          return movie.seen; 
        });  
      }, 
    }, 
    methods: { 
            
    } 
  }); 
  
*{ 
    box-sizing: border-box; 
  } 
   
  body{ 
    font-size: 15px; 
    font-family: 'Open Sans', sans-serif; 
    color: #444; 
    background-color: #696b65; 
    background-repeat: no-repeat; 
    background-size: cover; 
    padding: 50px 20px; 
    margin: 0; 
    min-height: 100vh; 
    position: relative; 
  } 
   
  .container{ 
    width: 400px; 
    max-width: 100%; 
    min-height: 500px; 
    margin: 20px auto 40px; 
    border: 1px solid #eee; 
    border-radius: 4px; 
    padding: 40px 20px; 
    -webkit-box-shadow: 0 0 15px 0 rgba(0,0,0,0.05); 
    box-shadow: 0 0 15px 0 rgba(0,0,0,0.05); 
    background-color: #f4f7fc; 
    overflow: hidden; 
    position: relative; 
  } 
   
  .todo-title{ 
    font-size: 1.2em; 
    color: #f65c65; 
    font-weight: normal; 
  } 
   
  form{ 
    overflow: overlay; 
  } 
   
  form label{ 
    display: block; 
    text-align: center; 
    font-size: 1.2em; 
  } 
   
  .btn, input { 
    line-height: 2em; 
    border-radius: 3px; 
    border: 0; 
    display: inline-block; 
    margin: 15px 0; 
    padding: 0.2em 1em; 
    font-size: 1em; 
  } 
   
  input[type='text'] { 
    border: 1px solid #ddd;  
    min-width: 80%; 
    transition: all ease-in 0.25s; 
  } 
   
  input:focus{ 
    outline: none; 
    border: 1px solid #a3b1ff; 
  } 
   
  input::placeholder{ 
    color: rgba(0,0,0,0.3); 
    font-style: italic; 
  } 
   
  .btn{ 
    text-align: center; 
    font-weight: bold;  
    cursor: pointer; 
    border-width: 1px; 
    border-style: solid; 
  } 
   
  .btn-add { 
    background: #ddd; 
    color: #fefefe; 
    border-color: #ddd; 
    min-width: 17%; 
    pointer-events: none; 
    transition: all ease-in 0.25s; 
    font-size: 2.2em; 
    line-height: 0.5em; 
    padding: 0.3em 0.3em; 
    float: right; 
  } 
   
  .btn-add.active{ 
    background: #6664ff; 
    border-color: #6664ff; 
    pointer-events: visible; 
  } 
   
  .btn-add.active:hover{ 
    background: #4442f6; 
    border-color: #4442f6; 
  } 
   
  .btn-add:active{ 
    transform: scale(0.95); 
  } 
  .control-buttons{ 
    position: absolute; 
    bottom: 20px; 
    left: 50%; 
    transform: translateX(-50%); 
    width: 100%; 
    text-align: center; 
  } 
  .btn-secondary{ 
    display: inline-block; 
    position: relative; 
    border: 0; 
    padding: 0; 
    margin: 0 10px; 
  } 
   
  .btn-secondary:after{ 
    position: absolute; 
    content: ''; 
    width: 0; 
    height: 3px; 
    background-color: #f4586e; 
    bottom: 0px; 
    left: 0; 
    transition: all ease-in 0.25s; 
  } 
   
  .btn-secondary:hover:after{ 
    width: 100%; 
  } 
   
   
  ul.container__movieList{ 
    padding: 0; 
    margin-bottom: 30px; 
  } 
   
  ul.container__movieList li{ 
    position: relative; 
    list-style-type: none; 
    display: block; 
    margin: 10px 0; 
    background: #e0e8f5; 
    border-radius: 3px; 
    padding-left: 38px;  
    padding-top: 12px; 
    padding-bottom: 12px; 
    padding-right: 49px;  
    overflow: hidden; 
  } 
   
  ul.container__movieList.archived li{ 
    background: #fff; 
  } 
   
  .container__movieList__film{ 
    position: relative; 
    display: inline-block; 
    padding: 0 0.5em; 
  } 
   
   
  ul.container__movieList li .delete{ 
    position: absolute; 
    height: 100%; 
    top: 50%; 
    right: 0; 
    transform: translateY(-50%); 
    cursor: pointer; 
    opacity: 0; 
    width: 0; 
    background-color: #f56468; 
    color: #fff; 
    transition: all ease-in 0.25s; 
  } 
     
  .container__movieList__seen{ 
    position: absolute;  
    opacity: 0; 
    display: none; 
  } 
   
  .container__movieList__seen + label { 
    position: absolute; 
    cursor: pointer; 
    left: 10px; 
    top: 50%; 
    transform: translateY(-50%); 
    width: 22px; 
    height: 22px; 
    border-radius: 2px; 
    border: 1px solid #cfdcec; 
    background-color: #fff; 
  } 
   
  .container__movieList__seen:checked + label:after{ 
    position: absolute; 
    content: ''; 
    top: 30%; 
    left: 50%; 
    height: 3px; 
    width: 6px; 
    border: solid #fc6c48; 
    border-width: 0 0 2px 2px; 
    transform-origin: center center; 
    transform: rotate(-45deg) translate(-50%, -50%); 
  } 
   
  .container__movieList__seen:checked + label:after{ 
    display: block; 
  } 
   
  .container__movieList__seen:checked ~ .container__movieList__film{ 
    color: #888; 
    text-decoration: line-through 
  } 
   
  
<html lang="en"> 
    <head> 
        <meta charset="UTF-8"> 
        <title>Test</title> 
        <link href="movieApp.css" rel="stylesheet"> 
        <script src="https://cdn.jsdelivr.net/npm/vue"></script>  
    </head> 
    <body>   
        <div id="app"> 
            <div class="container"> 
                <button>Рандом</button> 
                <input  
                    type="text" 
                    class="input-todo"  
                    v-model="search" 
                    placeholder="Поиск по фильмам" 
                > 
                <button>Фильтр</button> 
         
         
                <div> 
                    <ul class="container__movieList"> 
                        <li  
                            v-for="(movie, index) in filteredMovies"  
                            v-bind:key="movie.film" 
                        > 
                            <input  
                                class="container__movieList__seen"  
                                v-bind:id="'movie_' + movie.id"  
                                v-model="movie.seen"  
                                type="checkbox" 
                            > 
                            <label v-bind:for="'movie_' + movie.id"></label> 
                            <span class="container__movieList__film">{{ movie.film }}</span> 
                        </li> 
                    </ul> 
                </div> 
         
         
                <div> 
                    <p>Просмотренные</p> 
                    <ul class="container__movieList archived"> 
                        <li  
                            v-for="(movie, index) in watched"  
                            v-bind:key="movie.film" 
                        > 
                            <input  
                                class="container__movieList__seen"  
                                v-bind:id="'movie_' + movie.id"  
                                v-model="movie.seen"  
                                type="checkbox" 
                            > 
                            <label v-bind:for="'movie_' + movie.id"></label> 
                            <span class="container__movieList__film">{{ movie.film }}</span> 
                        </li> 
                    </ul> 
                </div> 
    <script src="movieApp.js"></script>   
    </body> 
</html> 

Answer 1

filteredMovies: function() { 
        let filtered = this.movies; 
            // if (this.search) { 
                filtered = this.movies.filter( 
                m => m.film.toLowerCase().indexOf(this.search) > -1 && !m.seen); 
             
        return filtered;

READ ALSO
Как рекурсивно вывести список файлов в папке?

Как рекурсивно вывести список файлов в папке?

Как вывести список файлов в папке рекурсивно, тоесть если в папке есть еще одно папка то вывести файлы для нее и тдНапример

134
Отправить форму, обнулить поля и вывести сообщение

Отправить форму, обнулить поля и вывести сообщение

Есть форма, но после отправки поля не очищаются, перепробовал кучу вариантов, памагити

122
jQuery плагин Revealator

jQuery плагин Revealator

https://githubcom/QODIO/revealator Подскажите пожалуйста, как отключить его на маленьких разрешениях?

172