JSFiddle - React, Tailwind, and code Playground

by marketingaddict8

HTML

<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/index.css">
<section class="todoapp">
  <header class="header">
    <h1>todos</h1>
    <input class="new-todo" autofocus autocomplete="off" placeholder="What needs to be done?" v-model="newTodo" @keyup.enter="addTodo">
  </header>
  <section class="main" v-show="todos.length">
    <ul class="todo-list">
      <li v-for="todo in todosList" class="todo" :key="todo.id" :class="{ editing: todo == editedTodo }">
        <div class="view">
          
          <label @click="editTodo(todo)">{{ todo.title }}</label>
          <button class="destroy" @click="removeTodo(todo)"></button>
        </div>
        <input class="edit" type="text" v-model="todo.title" v-todo-focus="todo == editedTodo" @blur="doneEdit(todo)" @keyup.enter="doneEdit(todo)" @keyup.esc="cancelEdit(todo)">
      </li>
    </ul>
  </section>
</section>

CSS

[v-cloak] {
  display: none;
}

.todo-list {
  overflow: auto;
}

JavaScript

// Full spec-compliant TodoMVC with localStorage persistence
// and hash-based routing in ~120 effective lines of JavaScript.

// localStorage persistence
var STORAGE_KEY = 'todos-vuejs-2.0'
var todoStorage = {
  fetch: function() {
    var todos = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]')
    todos.forEach(function(todo, index) {
      todo.id = index
    })
    todoStorage.uid = todos.length
    return todos
  },
  save: function(todos) {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))
  }
}

// app Vue instance
var app = new Vue({
  // app initial state
  data: {
    todos: todoStorage.fetch(),
    newTodo: '',
    editedTodo: null,
    /* visibility: 'all' */
  },

  // watch todos change for localStorage persistence
  watch: {
    todos: {
      handler: function(todos) {
        todoStorage.save(todos)
      },
      deep: true
    }
  },

  // computed properties
  // http://vuejs.org/guide/computed.html
  computed: {
    todosList: function() {
      return this.todos;
    },
  },


  // methods that implement data logic.
  // note there's no DOM manipulation here at all.
  methods: {
    addTodo: function() {
      var value = this.newTodo && this.newTodo.trim()
      if (!value) {
        return
      }
      this.todos.push({
        id: todoStorage.uid++,
        title: value,
        /* completed: false */
      })
      this.newTodo = ''
    },

    removeTodo: function(todo) {
      this.todos.splice(this.todos.indexOf(todo), 1)
    },

    editTodo: function(todo) {
      this.beforeEditCache = todo.title
      this.editedTodo = todo
    },

    doneEdit: function(todo) {
      if (!this.editedTodo) {
        return
      }
      this.editedTodo = null
      todo.title = todo.title.trim()
      if (!todo.title) {
        this.removeTodo(todo)
      }
    },

    cancelEdit: function(todo) {
      this.editedTodo = null
      todo.title = this.beforeEditCache
    },
  },

  // a custom directive to wait for the DOM to be...