Inicio Aplicacion TODO con VUE
Post
Cancel

Aplicacion TODO con VUE

Plugins y extensiones recomendadas

Creacion de Proyecto

  • Crear Proyecto con Vue CLI o UI VUE CLI CLI de Vue

VUE CLI CLI de Vue

  • Limpiar App.vue y borrar componente HelloWorld.vue
1
2
3
4
5
6
7
8
9
10
<template>
Hello World!
</template>

<script>

export default {
  name: 'App',
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html lang="">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <link rel="icon" href="<%= BASE_URL %>favicon.ico">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css" integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g==" crossorigin="anonymous"
    referrerpolicy="no-referrer" />
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">

  <title>
    <%= htmlWebpackPlugin.options.title %>
  </title>
</head>

<body>
  <noscript>
    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
  </noscript>
  <div id="app"></div>
  <!-- built files will be auto injected -->
</body>

</html>

Componente TodoApp.vue

  • Crear componentes TodoApp.vue (componente principal)
1
2
3
4
5
6
7
8
9
10
<template>
  <h1>ToDos</h1>
</template>

<script>
export default {

}
</script>

  • Llamar componente TodoApp.vue a App.vue. Agregar div con class container
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<div class="container">
  <todo-app />
</div>
  
</template>

<script>
import TodoApp from './components/TodoApp.vue'

export default {
  components: { TodoApp },
  name: 'App',
}
</script>
  • Revisar App en navegador

VUE APP Aplicacion de Vue en el navegador

Componente TodoFormulario.vue

  • Crear Componente TodoFormulario.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
    <form>
        <input
          type="text"
          class="form-control my-3"
          placeholder="Ingresar ToDo">
    </form>
</template>

<script>
export default {

}
</script>
  • Importar componente TodFormulario.vue a Todoapp-vue
1
2
3
4
5
6
7
8
9
10
11
12
<template>
  <h1>ToDos</h1>
  <todo-formulario />
</template>

<script>
import TodoFormulario from './TodoFormulario.vue'
export default {
  components: { TodoFormulario },

}
</script>
  • Revisar App en el navegador

VUE APP Aplicacion de Vue en el navegador

  • Utilizando composition API crearemos un arreglo en el componente padre TodoApp que podra ser accedido por sus componentes hijos. Creando una constante ref y enviandola a traves de un provide.

Vue Ref

Vue Provide-Inject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
    <h1>ToDos</h1>
    <todo-formulario />
</template>

<script>
import { provide, ref } from 'vue'
import TodoFormulario from './TodoFormulario.vue'
export default {
    components: { TodoFormulario },
    setup(){
        const todos = ref([])
        provide('todos', todos)
    }
}
</script>
  • Se configura TodoFormulario.vue para recibir data del padre a traves de inject
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
    <form>
        <input
          type="text"
          class="form-control my-3"
          placeholder="Ingresar ToDo">
    </form>
</template>

<script>
import { inject } from '@vue/runtime-core'
export default {
    setup(){
        const todos = inject('todos')
        console.log(todos.value)
    }
}
</script>
  • Inspeccionar consola en el navegador y ver tambien Vuetools

  • Crear funcion agregarToDo en TodoFormulario.vue y vincularlo con el template, verificar funcionamiento en consola del navegador

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
    <form @submit.prevent="agregarToDo">
        <input
          type="text"
          class="form-control my-3"
          placeholder="Ingresar ToDo">
    </form>
</template>

<script>
import { inject } from '@vue/runtime-core'
export default {
    setup(){
        const todos = inject('todos')
        
        const agregarToDo = () => {
            console.log('agregaste un TODO')
        }

        return{agregarToDo}
    }
}
</script>
  • Agregar en TodoFormulario.vue un v-model para enviar datos del input a la funcion agregarToDo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
    <form @submit.prevent="agregarToDo">
        <input
          type="text"
          class="form-control my-3"
          placeholder="Ingresar ToDo"
          v-model="texto">
    </form>
</template>

<script>
import { inject, ref } from '@vue/runtime-core'
export default {
    setup(){
        const todos = inject('todos')
        const texto = ref('')
        
        const agregarToDo = () => {
            console.log(texto.value)
        }

        return{agregarToDo, texto}
    }
}
</script>
  • Construir objeto todo (singular) que contenga los datos a utilizar: id, texto, estado.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<template>
    <form @submit.prevent="agregarToDo">
        <input
          type="text"
          class="form-control my-3"
          placeholder="Ingresar ToDo"
          v-model="texto">
    </form>
</template>

<script>
import { inject, ref } from '@vue/runtime-core'
export default {
    setup(){
        const todos = inject('todos')
        const texto = ref('')
        
        const agregarToDo = () => {

            const todo = {
                descripcion: texto.value,
                estado: false,
                id: Date.now()
            }
            console.log(todo)
        }   

        return{agregarToDo, texto}
    }
}
</script>
  • Se crean validaciones para texto, vacio y tambien se limpia el texto del formulario
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<template>
    <form @submit.prevent="agregarToDo">
        <input
          type="text"
          class="form-control my-3"
          placeholder="Ingresar ToDo"
          v-model.trim="texto">
    </form>
</template>

<script>
import { inject, ref } from '@vue/runtime-core'
export default {
    setup(){
        const todos = inject('todos')
        const texto = ref('')
        
        const agregarToDo = () => {
            if(texto.value === ''){
                console.log('vacio')
                return
            }
            const todo = {
                descripcion: texto.value,
                estado: false,
                id: Date.now()
            }

            texto.value = ''
            console.log(todo)
        }   

        return{agregarToDo, texto}
    }
}
</script>
  • A traves del metodo push empujamos o enviamos el objeto todo al arreglo todos que se almacenara en el componente padre TodoApp.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<template>
    <form @submit.prevent="agregarToDo">
        <input
          type="text"
          class="form-control my-3"
          placeholder="Ingresar ToDo"
          v-model.trim="texto">
    </form>
</template>

<script>
import { inject, ref } from '@vue/runtime-core'
export default {
    setup(){
        const todos = inject('todos')
        const texto = ref('')
        
        const agregarToDo = () => {
            if(texto.value === ''){
                console.log('vacio')
                return
            }
            const todo = {
                descripcion: texto.value,
                estado: false,
                id: Date.now()
            }

            todos.value.push(todo)
            console.log(todos.value)

            texto.value = ''
            //console.log(todo)
        }   

        return{agregarToDo, texto}
    }
}
</script>
  • Verificar arreglo en la consola del navegador
  • Agregar watchEffect a TodoApp.vue para esperar el retorno de los todo individuales. Comentar console.log(todo.value) de TodoFormulario.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
    <h1>ToDos</h1>
    <todo-formulario />
</template>

<script>
import { provide, ref, watchEffect } from 'vue'
import TodoFormulario from './TodoFormulario.vue'
export default {
    components: { TodoFormulario },
    setup(){
        const todos = ref([])
        provide('todos', todos)

        watchEffect(() => {
            console.log(todos.value.length)
            console.log(todos.value)
        })
    }
}
</script>

Componente TodoListado.vue

  • Crear componente TodoListado.vue, que mostrara el contenido del arreglo con los todos e importarlo a TodoApp.vue
1
2
3
4
5
6
7
8
9
<template>
    Listado de TODOS
</template>

<script>
export default {

}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
    <h1>ToDos</h1>
    <todo-formulario />
    <todo-listado />
</template>

<script>
import { provide, ref, watchEffect } from 'vue'
import TodoFormulario from './TodoFormulario.vue'
import TodoListado from './TodoListado.vue'
export default {
    components: { TodoFormulario, TodoListado },
    setup(){
        const todos = ref([])
        provide('todos', todos)

        watchEffect(() => {
            console.log(todos.value.length)
            console.log(todos.value)
        })
    }
}
</script>
  • Verificar en el navegador con la consola

Componente TodoItem.vue

  • Modificar TodoListado.vue para contener un list group como el ejemplo de List group BootStrap, donde el ul quedara en TodoListado.vue y el li en un nuevo componente llamado TodoItem.vue (el cual estara dentro de TodoListado)
1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
    <ul class="list-group">
        <todo-item />
    </ul>
</template>

<script>
import TodoItem from './TodoItem.vue'
export default {
  components: { TodoItem },

}
</script>
1
2
3
4
5
6
7
8
9
<template>
      <li class="list-group-item">Cras justo odio</li>
</template>

<script>
export default {

}
</script>
  • Recorrer el arreglo todo disponible en el componente padre con un v-for dentro del componente TodoListado.vue. Se manda a traves de un prop el valor del todo a TodoItem.vue. Vue props
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
    <ul class="list-group">
        <todo-item 
            v-for="todo in todos" :key="todo.id"
            :todo="todo"
        />
    </ul>
</template>

<script>
import { inject } from '@vue/runtime-core'
import TodoItem from './TodoItem.vue'
export default {
  components: { TodoItem },
  setup(){
    const todos = inject('todos')

    return {todos}
  }
}
</script>
  • Se modifica TodoItem.vue para recibir el prop, agregando estilos para cada item en el listado
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
      <li class="list-group-item d-flex justify-content-between">
        <span role="button">
            { { todo.descripcion } }
        </span>
        <span role="button">
            <i class="fas fa-times"></i>
        </span>
      </li>
</template>

<script>
export default {
    props: {
        todo: {
            type: Object,
            required: true
        }
    }
}
</script>
  • Verificar la app en el navegador VUE APP Aplicacion de Vue en el navegador

  • Agregar funcionabilidad de borrar item utilizar el metodo filter. Filter JS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<template>
    <li class="list-group-item d-flex justify-content-between">
        <span role="button">
            { { todo.descripcion } }
        </span>
        <span role="button" @click="borrar(todo.id)">
            <i class="fas fa-times"></i>
        </span>
    </li>
</template>

<script>
import { inject } from '@vue/runtime-core'
export default {
    props: {
        todo: {
            type: Object,
            required: true
        }
    },
    setup() {
        const todos = inject('todos')

        const borrar = id => {
            todos.value = todos.value.filter(item => item.id !== id)
        }

        return {borrar}
    }
}
</script>
  • Agregar funcionalidad de cambiar estado completado, tachado es true, sin completar es false. Podemos utilizar el metodo map. Map JS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<template>
    <li class="list-group-item d-flex justify-content-between">
        <span role="button" @click="completado(todo.id)">
            { { todo.descripcion } }
        </span>
        <span role="button" @click="borrar(todo.id)">
            <i class="fas fa-times"></i>
        </span>
    </li>
</template>

<script>
import { inject } from '@vue/runtime-core'
export default {
    props: {
        todo: {
            type: Object,
            required: true
        }
    },
    setup() {
        const todos = inject('todos')

        const borrar = id => {
            todos.value = todos.value.filter(item => item.id !== id)
        }

        const completado = id => {
            todos.value = todos.value.map(item => {
                if(item.id === id){
                    item.estado = true
                }
                return item
            })
        }

        return { borrar, completado }
    }
}
</script>
  • Agregamos que al cambiar estado tache el texto del item. Ademas modificamos para que cambie entre estado al dar click nuevamente al item.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<template>
    <li class="list-group-item d-flex justify-content-between">
        <span role="button" @click="completado(todo.id)" :class="{ 'tachado': todo.estado }">
            { { todo.descripcion } }
        </span>
        <span role="button" @click="borrar(todo.id)">
            <i class="fas fa-times"></i>
        </span>
    </li>
</template>

<script>
import { inject } from '@vue/runtime-core'
export default {
    props: {
        todo: {
            type: Object,
            required: true
        }
    },
    setup() {
        const todos = inject('todos')

        const borrar = id => {
            todos.value = todos.value.filter(item => item.id !== id)
        }

        const completado = id => {
            todos.value = todos.value.map(item => {
                if (item.id === id) {
                    /*if (item.estado == false) {
                        item.estado = true
                    } else {
                        item.estado = false
                    }*/
                    item.estado = !item.estado
                }
                return item
            })
        }

        return { borrar, completado }
    }
}
</script>

<style>
.tachado {
    text-decoration: line-through;
}
</style>

Componente TodoFooter.vue

  • Crear componente TodoFooter.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
    <li class="list-group-item d-flex justify-content-between">
        <span role="button">
            ## Pendientes
        </span>
        <span role="button">
            Eliminar completados
        </span>
    </li>
</template>

<script>
export default {

}
</script>
  • Agregar el componente TodoFooter.vue al componente TodoListado.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
    <ul class="list-group">
        <todo-item 
            v-for="todo in todos" :key="todo.id"
            :todo="todo"
        />

        <todo-footer />
    </ul>
</template>

<script>
import { inject } from '@vue/runtime-core'
import TodoItem from './TodoItem.vue'
import TodoFooter from './TodoFooter.vue'
export default {
  components: { TodoItem, TodoFooter },
  setup(){
    const todos = inject('todos')

    return {todos}
  }
}
</script>
  • Verificar la app en el navegador VUE APP Aplicacion de Vue en el navegador

  • Agregar funcionalidad para que el footer sea dinamico. Debe mostrarse cuando hay items en la lista y ocultarse cuando no existan.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<template>
  <ul class="list-group">
    <todo-item
      v-for="todo in todos"
      :key="todo.id"
      :todo="todo" />
    <li
      v-if="todos.length == 0"
      class="list-group-item">
      No hay ToDos
    </li>
    <todo-footer
      v-if="todos.length !== 0" />
  </ul>
</template>

<script>
import { inject } from '@vue/runtime-core'
import TodoItem from './TodoItem.vue'
import TodoFooter from './TodoFooter.vue'
export default {
  components: { TodoItem, TodoFooter },
  setup() {
    const todos = inject('todos')

    return { todos }
  }
}
</script>
  • Se implementa en TodoFooter.vue un funcion de tipo computed para el conteo de items pendientes (estado == false)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
    <li class="list-group-item d-flex justify-content-between">
        <span role="button">
            { { contarPendientes } } Pendientes
        </span>
        <span role="button">
            Eliminar completados
        </span>
    </li>
</template>

<script>
import { computed, inject } from '@vue/runtime-core'
export default {
    setup(){
        const todos = inject('todos')

        const contarPendientes = computed(() => {
            return todos.value.filter(item => item.estado === false).length
        })

        return { contarPendientes }
    }
}
</script>
  • Se implementa en TodoFooter.vue un funcion para Eliminar items completados (estado == true) pero al utilizar filter le solicitamos crear un nuevo array solo con los elementos pendientes o que esten en false.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<template>
    <li class="list-group-item d-flex justify-content-between">
        <span role="button">
            { { contarPendientes } } Pendientes
        </span>
        <span role="button" @click="eliminarCompletados">
            Eliminar completados
        </span>
    </li>
</template>

<script>
import { computed, inject } from '@vue/runtime-core'
export default {
    setup() {
        const todos = inject('todos')

        const contarPendientes = computed(() => {
            return todos.value.filter(item => item.estado === false).length
        })

        const eliminarCompletados = () => {
            todos.value = todos.value.filter(item => item.estado === false)
        }

        return { contarPendientes, eliminarCompletados }
    }
}
</script>

Componente TodoFiltro.vue

  • Se crea un nuevo componente llamado TodoFiltro.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<template>
    <div class="btn-group mt-3 d-flex" role="group" aria-label="Filtro">
        <button type="button" class="btn">Pendientes</button>
        <button type="button" class="btn">Todos</button>
        <button type="button" class="btn">Completados</button>
    </div>
</template>

<script>
export default {

};

</script>
  • Este nuevo componente se utilizara dentro de TodoListado.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<template>
  <ul class="list-group">
    <todo-item
      v-for="todo in todos"
      :key="todo.id"
      :todo="todo" />
    <li
      v-if="todos.length == 0"
      class="list-group-item">
      No hay ToDos
    </li>
    <todo-footer
      v-if="todos.length !== 0" />
  </ul>

  <todo-filtro />
</template>

<script>
import { inject } from '@vue/runtime-core'
import TodoItem from './TodoItem.vue'
import TodoFooter from './TodoFooter.vue'
import TodoFiltro from './TodoFiltro.vue'
export default {
  components: { TodoItem, TodoFooter, TodoFiltro },
  setup() {
    const todos = inject('todos')

    return { todos }
  }
}
</script>
  • Verificar la app en el navegador VUE APP Aplicacion de Vue en el navegador

  • En el componente TodoListado.vue creamos una constante que enviaremos por ref al componente TodoFiltro. Dicha referencia nos servira para recorrer el arreglo y poder enviar variables de estado al filtro

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<template>
  <ul class="list-group">
    <todo-item
      v-for="todo in todos"
      :key="todo.id"
      :todo="todo" />
    <li
      v-if="todos.length == 0"
      class="list-group-item">
      No hay ToDos
    </li>
    <todo-footer
      v-if="todos.length" />
  </ul>

  <todo-filtro />
</template>

<script>
import { computed, inject, provide, ref } from '@vue/runtime-core'
import TodoItem from './TodoItem.vue'
import TodoFooter from './TodoFooter.vue'
import TodoFiltro from './TodoFiltro.vue'
export default {
  components: { TodoItem, TodoFooter, TodoFiltro },
  setup() {
    const todosApp = inject('todos')
    const estado = ref('all')

    const todos = computed(() => {
      if(estado.value === 'all'){
        return todosApp.value
      }
      if(estado.value === 'pendientes'){
        return todosApp.value.filter(item => item.estado === false)
      }
      if(estado.value === 'completados'){
        return todosApp.value.filter(item => item.estado === true)
      }
    })

    provide('estado', estado)

    return { todos }
  }
}
</script>
  • Modificamos el componente TodoFiltro para que pueda acceder a los estados y poder filtrar adecuadamente con los botones de filtro
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<template>
  <div class="btn-group mt-3 d-flex" role="group" aria-label="Filtro">
    <button 
      type="button" 
      class="btn"
      @click="filtro('pendientes')"
      :class="estado === 'pendientes' ? 'btn-success' : 'btn-dark'"
    >Pendientes</button>
    <button 
      type="button" 
      class="btn"
      @click="filtro('all')"
      :class="estado === 'all' ? 'btn-success' : 'btn-dark'"
    >Todos</button>
    <button 
      type="button" 
      class="btn"
      @click="filtro('completados')"
      :class="estado === 'completados' ? 'btn-success' : 'btn-dark'"
    >Completados</button>
  </div>
</template>

<script>
import { inject } from "vue";
export default {
  setup() {
    const estado = inject("estado");
    const filtro = (valor) => {
      estado.value = valor;
    };
    return { filtro, estado };
  },
};
</script>
  • Finalmente utilizamos LocalStorage para guardar la data en el navegador. Pro lo que editamos el componente TodoApp.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
    <h1>ToDos</h1>
    <todo-formulario />
    <todo-listado />
</template>

<script>
import { provide, ref, watchEffect } from 'vue'
import TodoFormulario from './TodoFormulario.vue'
import TodoListado from './TodoListado.vue'
export default {
    components: { TodoFormulario, TodoListado },
    setup() {
        const todos = ref([])
        provide('todos', todos)

        if (localStorage.getItem('todos')) {
            todos.value = JSON.parse(localStorage.getItem('todos'))
        }

        watchEffect(() => {
            localStorage.setItem('todos', JSON.stringify(todos.value))
            //console.log(todos.value.length)
            //console.log(todos.value)
        })
    }
}
</script>

Estilos CSS

  • App.vue CSS
1
2
3
4
5
6
7
8
9
10
11
12
13
<style>
body {
  background-image: url(./assets/bg-desktop-dark.jpg);
  background-repeat: no-repeat;
  background-size: 100% 200px;
  background-color: #222222
}

.container {
  margin-top: 70px;
  max-width: 700px;
}
</style>
  • TodoApp.vue CSS
1
2
3
4
5
<style>
h1 {
    color: #ffffff;
}
</style>
  • TodoFormulario.vue CSS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<style>
input[type="text"] {
    font-family: sans-serif;
    font-size: 18px;
    font-weight: 400;
    line-height: 12px;
    color: #d8d8d8;
    border: none;
    flex-grow: 1;
    background-color: #25273d;
    box-sizing: border-box;
    height: 48px;
}

input[type="text"]:focus {
    outline: none;
    color: #d8d8d8;
    background-color: #25273d;
}
</style>
  • TodoItem.vue CSS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<style>
.tachado {
    text-decoration: line-through;
}

.list-group-item {
    min-width: 300px;
    width: 100%;
    background-color: #25273d;
    border-radius: 5px;
    color: #d8d8d8;
}

.fa-times {
    color: red;
}
</style>
  • Verificar la app en el navegador VUE APP Aplicacion de Vue en el navegador

  • Finalmente ejecutamos el comando npm run build. La aplicacion quedara lista para ser distribuida en la carpeta dist del proyecto

1
npm run build
This post is licensed under CC BY 4.0 by the author.