Tạo ứng dụng effect đẹp mắt với Transitions & Animation - VueJS
Giới thiệu Tiếp tục trong series 2018 - Cùng nhau học VueJS, hôm nay mình sẽ tạo một ứng dụng nho nhỏ với Transitions & Animation. Link github: https://github.com/vanquynguyen/vue-cli-timetable . Link demo: https://vanquynguyen.github.io/vue-cli-timetable Ứng dụng có kết hợp giữa VueCLI, ...
Giới thiệu
Tiếp tục trong series 2018 - Cùng nhau học VueJS, hôm nay mình sẽ tạo một ứng dụng nho nhỏ với Transitions & Animation. Link github: https://github.com/vanquynguyen/vue-cli-timetable . Link demo: https://vanquynguyen.github.io/vue-cli-timetable Ứng dụng có kết hợp giữa VueCLI, event handling, Form Input Bindings và Transitions & Animation.
Nội dung
Khởi tạo VueCLI Trước khi tạo một VueCLI, đảm bảo rằng bạn đã cài npm hoặc yarn. Mình thì dùng npm =)), bạn nào cài yarn thì vào đây nhé https://yarnpkg.com/en/. Kiểm tra xem máy của bạn đã cài đặt nodejs và npm chưa
$ nodejs -v v9.4.0 $ npm -v 5.6.0
Cài đặt vue-cli
$ npm install -g vue-cli
Sau khi cài đặt xong dùng lệnh bên dưới để tạo 1 project vue-cli
$ vue init webpack vue-cli-timetable
Trong file App.vue:
<template> <div class="container"> <div class="row"> <div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3"> <h1>Time table ({{tasks.length}})</h1> <hr> <br><br> </div> </div> <form @submit="addTask"> <div class="form-group"> <input v-model="newTask" class="form-control" placeholder="Tôi muốn..."> </div> </form> <button class="btn btn-danger" @click="shuffle">Đổi chỗ</button> <div v-for="(check, index) in checks" v-bind:key="index"> <input type="checkbox" v-model="checked" v-bind:value="check" /> {{check}} </div> <span>Checked: {{ checked }}</span> <div class="row"> <div class="form-group"> <div class="searchable-container"> <transition-group name="list-complete" tag="p"> <div class="tasks col-xs-5 col-sm-5 col-md-2 col-lg-2" v-for="(task, index) in filteredTasks" v-bind:key="index"> <div class="info-block block-info clearfix"> <div class="square-box pull-left"> <span class="glyphicon glyphicon-tags glyphicon-lg"></span> <span class="glyphicon glyphicon-trash glyphicon-lg" @click="removeTask(index)"></span> </div> <div data-toggle="buttons" class="btn-group bizmoduleselect"> <label class="btn btn-default" id="check" @click="checkBox(index)"> <div class="bizcontent"> <input type="checkbox" autocomplete="off"> <span class="glyphicon glyphicon-ok glyphicon-lg"></span> <h5>{{task.body}}</h5> </div> </label> </div> </div> <br> </div> </transition-group> </div> </div> </div> </div> </template> <script> export default { data () { return { tasks: [ {body:"Ăn cơm", check:"Unchecked", completed: false}, {body:"Tán gái", check:"Unchecked", completed: false}, {body:"Lướt face", check:"Unchecked", completed: false}, {body:"Học Vue", check:"Unchecked", completed: false}, {body:"Ngắm gái", check:"Unchecked", completed: false}, {body:"Nhậu", check:"Unchecked", completed: false}, {body:"Học Laravel", check:"Unchecked", completed: false}, {body:"Ngủ", check:"Unchecked", completed: false}, {body:"Play game", check:"Unchecked", completed: false}, {body:"Play girl", check:"Unchecked", completed: false}, ], checks: ['Checked', 'Unchecked'], newTask: ', checked: [], } }, computed: { filteredTasks(){ let filterTasks = this.tasks; $.each(this.checked, function(value, key){ filterTasks= filterTasks.filter(function(task){ return task.check == key; }) }); return filterTasks; } }, methods: { checkBox(indexTask) { this.tasks[indexTask].check = 'Checked'; }, addTask(e){ e.preventDefault(); this.tasks.push({ body: this.newTask, check: "Unchecked", completed: false }); this.newTask = '; }, removeTask(index) { Vue.delete(this.tasks, index); }, shuffle() { this.tasks = _.shuffle(this.tasks) }, } } </script>
Import file App.vue và style.css vào file main.js
import Vue from 'vue' import App from './App.vue' import './style.css'; new Vue({ el: '#app', render: h => h(App) })
Đừng quên viết css cho ứng dụng, tạo file style.css
ul li { list-style-type: none; } .slide-fade-enter-active { transition: all .3s ease; } .slide-fade-leave-active { transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0); } .slide-fade-enter, .slide-fade-leave-to /* .slide-fade-leave-active below version 2.1.8 */ { transform: translateX(10px); opacity: 0; } .searchable-container{margin:20px 0 0 0} .searchable-container label.btn-default.active{background-color:#007ba7;color:#FFF} .searchable-container label.btn-default{awidth:90%;border:1px solid #efefef;margin:5px; box-shadow:5px 8px 8px 0 #ccc;} .searchable-container label .bizcontent{awidth:100%;} .searchable-container .btn-group{awidth:90%} .searchable-container .btn span.glyphicon{ opacity: 0; } .searchable-container .btn.active span.glyphicon { opacity: 1; } .tasks { transition: all 1s; display: inline-block; margin-right: 10px; } .list-complete-enter, .list-complete-leave-to /* .list-complete-leave-active below version 2.1.8 */ { opacity: 0; transform: translateY(30px); } .list-complete-leave-active { position: absolute; } .row { padding-left: 122px; }
Cuối cùng là file index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>vue-cli</title> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> <script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.1/lodash.min.js"></script> </head> <body> <div id="app"></div> <script src="dist/build.js"></script> </body> </html>
Lời kết
:face_with_hand_over_mouth::face_with_hand_over_mouth::face_with_hand_over_mouth: Hãy theo dõi series 2018 - Cùng nhau học VueJS cùng học tập và góp ý để nâng cao kiến thức về VueJs.