学习 vue3 从最基础开始,步步完善,最终完成

实现简单的todolist

jQuery思维类似这样

<div>
<h2 id="app"></h2>
<input type="text" id="todo-input">
</div>
<script src="jquery.min.js"></script>
<script>
// 找到输入框,监听输入
$('#todo-input').on('input',function(){
let val = $(this).val() // 获取值
$('#app').html(val) // 找到标签,修改内容
})
</script>

Vue 思维

<body>
<div id="app">
  <h2>{{title}}</h2>
  <input type="text" v-model="title" />
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
  const App = {
    data() {
      return {
        title: '', // 定义一个数据
      }
    },
  }
  // 启动应用
  Vue.createApp(App).mount('#app')
</script>
</body>

image.png

区别在于 jQuery 时代的开发逻辑,就是我们先要找到目标元素,然后再进行对应的修改。Vue 时代不要再思考页面的元素怎么操作,而是要思考数据是怎么变化的。

如果有多个想做的事

使用 v-for 循环展示数据

<body>
  <div id="app">
    <h2>{{ title }}</h2>
    <input type="text" v-model="title" />
    <ul>
      <li v-for="todo in todos">{{ todo }}</li>
    </ul>
  </div>

  <!-- 使用完整版 Vue(带模板编译器) -->
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <script>
    const App = {
      data() {
        return {
          title: '',
          todos: ['赖床', '熬夜', '要不改改?'],
        }
      },
    }
    Vue.createApp(App).mount('#app')
  </script>
</body>

image.png

添加交互

<body>
  <div id="app">
    <input type="text" v-model="title" @keydown.enter="addTodo" />
    <ul>
      <li v-for="todo in todos">{{todo}}</li>
    </ul>
  </div>
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <script>
    const App = {
      data() {
        return {
          title: '', // 定义一个数据
          todos: ['赖床', '熬夜', '要不改改?'],
        }
      },
      methods: {
        addTodo() {
          this.todos.push(this.title)
          this.title = ''
        },
      },
    }
    // 启动应用
    Vue.createApp(App).mount('#app')
  </script>
</body>

image.png

勾选完成并置灰

需要加一个 是否完成状态

<body>
  <div id="app">
    <input type="text" v-model="title" @keydown.enter="addTodo" />
    <ul>
      <li v-for="todo in todos">
        <input type="checkbox" v-model="todo.done" />
        <span :class="{done:todo.done}"> {{todo.title}}</span>
      </li>
    </ul>
  </div>
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <script>
    const App = {
      data() {
        return {
          title: '', // 定义一个数据
          todos: [
            { title: '赖床', done: true },
            { title: '熬夜', done: true },
            { title: '要不改改?', done: false },
          ],
        }
      },
      methods: {
        addTodo() {
          this.todos.push({
            title: this.title,
            done: false,
          })
          this.title = ''
        },
      },
    }
    // 启动应用
    Vue.createApp(App).mount('#app')
  </script>

  <style>
    .done {
      color: gray;
      text-decoration: line-through;
    }
  </style>
</body>

image.png

添加已完成/未完成数量

<body>
  <div id="app">
    <input type="text" v-model="title" @keydown.enter="addTodo" />
    <ul>
      <li v-for="todo in todos">
        <input type="checkbox" v-model="todo.done" />
        <span :class="{done:todo.done}"> {{todo.title}}</span>
      </li>
    </ul>

    <div>
      全选<input type="checkbox" v-model="allDone" />
      <span> {{active}} / {{all}} </span>
    </div>
  </div>
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <script>
    const App = {
      data() {
        return {
          title: '', // 定义一个数据
          todos: [
            { title: '赖床', done: true },
            { title: '熬夜', done: true },
            { title: '要不改改?', done: false },
          ],
        }
      },
      computed: {
        active() {
          return this.todos.filter((v) => !v.done).length
        },
        all() {
          return this.todos.length
        },
        allDone: {
          get: function () {
            return this.active === 0
          },
          set: function (val) {
            this.todos.forEach((todo) => {
              todo.done = val
            })
          },
        },
      },
      methods: {
        addTodo() {
          this.todos.push({
            title: this.title,
            done: false,
          })
          this.title = ''
        },
      },
    }
    // 启动应用
    Vue.createApp(App).mount('#app')
  </script>

  <style>
    .done {
      color: gray;
      text-decoration: line-through;
    }
  </style>
</body>

image.png

image.png

条件渲染 清理按钮

<button v-if="active<all" @click="clear">清理</button>
<script>
methods:{
clear(){
this.todos = this.todos.filter(v=>!v.done)
}
}
</script>

image.png

点击清理后

image.png

如果全部都清理 展示暂无数据

    <ul v-if="todos.length">
      <li v-for="todo in todos">
        <input type="checkbox" v-model="todo.done" />
        <span :class="{done:todo.done}"> {{todo.title}}</span>
      </li>
    </ul>
    <div v-else>暂无数据</div>

image.png

缓存数据 刷新依旧有效

const STORAGE_KEY = 'todos_v1'

      mounted() {
        try {
          const saved = localStorage.getItem(STORAGE_KEY)
          if (saved) this.todos = JSON.parse(saved)
        } catch (e) {
          console.warn('restore failed', e)
        }
      },
      watch: {
        todos: {
          handler(list) {
            localStorage.setItem(STORAGE_KEY, JSON.stringify(list))
          },
          deep: true,
        },
      },

image.png

image.png

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:[email protected]