快速写你的第一个vue3.0—Todolist吧~

前言

很多时候,当我们面对着新技术的到来,有些人看文档已经大概了解其中缘由,甚至已经能直接上手项目。但,是不是还会有一些刚入门的小伙伴,对于新技术可谓是又爱又恨。其实,不要害怕写错代码,要勇于尝试,要在错误的代码中寻找自己的薄弱点并攻破~ 加油,从写第一个todolist开始吧。

写给你们同时也是写给自己的一句话:快速成长的捷径就是勇于面对自己的薄弱点。

了解相关Api

setup

  • 大体介绍:setup 函数只执行一次,但后续对于数据的更新也依旧可以驱动视图更新.
  • 执行顺序:setup函数会在 beforeCreate之后 created之前执行.
  • 接收参数:props、context.
setup(props,context){
    console.log('props',props) // 组件参数
    console.log('context',context) // 上下文对象
    // context.slots
    // context.emit
    // context.refs
} 

reactive

  • 用于获取一个对象的响应性代理对象,等价于 Vue.observable () API,经过reactive处理后的函数能变成响应式的数据,某种程度来说,类似于option api里面的data属性的值.
setup() {
    // 这个类似于vue2中的data()返回的响应式对象
    const count = reactive({ count: 0 }) 
    return {
        count
    }
}

ref

  • 将给定的值创建一个响应式的数据对象.
setup() {
    const count = ref(0);
    function increment() {
      count.value++;
    }
    return {
      count,
      increment
    }
}

computed

  • 有时我们需要依赖于其他状态的状态——在 Vue 中,这是通过计算属性来处理的。 要直接创建一个计算值,我们可以使用computed.
const state = reactive({
    count: 0,
    plusOne: computed(() => state.count + 1)
})
  • 创建可读可写的计算属性
// 创建一个响应式数据
const count = ref(1) 
// 根据count的值创建一个响应式的计算属性, 它会根据ref自动计算并且返回一个新的ref
const computedCount = computed({
    get: () => count.value + 1,
    set: (val) => count.value = val - 1
} ) 
computedCount.count = 6
console.log(count.value) // 打印 5

watchEffect

  • 副作用函数,如果需要在响应式数据发生变化的时候做某件事,我们会可以使用 effect 函数.
  • 这个函数在读取 count.value 的时候会收集它作为依赖.
setup() {
    const count = ref(0)
    const add = () => count.value++
    watchEffect(()=>{
        console.log('count changed', count.value)
    })
    return { count, add }
}

编写Todolist

image

html部分

<template>
  <div class="todo">
    <div class="todo-form">
      <div class="todo-input">
        <input @keyup.enter="handleAddList" v-model="contentRef" type="text" placeholder="请输入事项内容" />
      </div>
      <button type="button" @click="handleAddList">添加事项</button>
    </div>
    <ul class="list" v-if="listRev.length">
      <li class="list-item" v-for="(item,index) of listRev" :id="item.id" :key="item.id">
        <div class="item-label" :class="item.status?'done':''">{{item.title}}</div>
        <div class="action-btn">
          <button class="success" v-if="!item.status" @click="handleStatusChange(index,true)">完成</button>
          <button class="reset" v-if="item.status" @click="handleStatusChange(index,false)">激活</button>
          <button class="delete" @click="handleRemove(index)">删除</button>
        </div>
      </li>
    </ul>
    <p v-else>暂无待办事项..</p>
  </div>
</template>

全部代码

<template>
  <div class="todo">
    <div class="todo-form">
      <div class="todo-input">
        <input @keyup.enter="handleAddList" v-model="contentRef" type="text" placeholder="请输入事项内容" />
      </div>
      <button type="button" @click="handleAddList">添加事项</button>
    </div>
    <ul class="list" v-if="listRev.length">
      <li class="list-item" v-for="(item,index) of listRev" :id="item.id" :key="item.id">
        <div class="item-label" :class="item.status?'done':''">{{item.title}}</div>
        <div class="action-btn">
          <button class="success" v-if="!item.status" @click="handleStatusChange(index,true)">完成</button>
          <button class="reset" v-if="item.status" @click="handleStatusChange(index,false)">激活</button>
          <button class="delete" @click="handleRemove(index)">删除</button>
        </div>
      </li>
    </ul>
    <p v-else>暂无待办事项..</p>
  </div>
</template>

<script lang="ts">
import { reactive, ref, watchEffect } from "vue";

// 事项接口
interface IList {
  id: number;
  title: string;
  status: boolean;
}
export default {
  setup() {
    let listRev = reactive<Array<IList>>([]);
    let contentRef = ref<string | null>(null);
    let idRef = ref<number>(0);
    // 事项添加
    const handleAddList = () => {
      if (!contentRef.value) return alert("请输入事项内容");
      if (listRev.find((item) => item.title === contentRef.value)) {
        return alert("该事项已存在,请输入其他事项吧~");
      }
      listRev.push({
        title: contentRef.value,
        id: ++idRef.value,
        status: false,
      });
      contentRef.value = "";
    };

    // 事项完成
    const handleStatusChange = (index: number, status: boolean) => {
      listRev[index].status = status;
    };

    // 事项删除
    const handleRemove = (index: number) => {
      listRev.splice(index, 1);
    };
    const count = ref(0);
    const add = () => count.value++;

    watchEffect(() => {
      console.log("contentRef changed", contentRef.value);
    });
    return {
      listRev,
      contentRef,
      handleAddList,
      handleStatusChange,
      handleRemove,
    };
  },
};
</script>

<style lang="scss">
button {
  border-width: 0px;
  border-radius: 3px;
  background: #1e90ff;
  cursor: pointer;
  outline: none;
  font-family: Microsoft YaHei;
  color: white;
  font-size: 14px;
}
.todo {
  padding: 5vw;
  .todo-form {
    display: flex;
    justify-content: space-between;
    .todo-input {
      width: 75%;
      text-align: left;
      input {
        width: 100%;
        border: 1px solid #ccc;
        padding: 10px 0px;
        border-radius: 3px;
        padding-left: 5px;
        box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
        transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;
      }
      input:focus {
        border-color: #66afe9;
        outline: 0;
        box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075),
          0 0 8px rgba(102, 175, 233, 0.6);
      }
    }
    button {
      width: 20%;
      font-size: 12px;
    }
    button:active {
      background: #5599ff;
    }
  }
  .list {
    text-align: left;
    vertical-align: top;
    background: #fff;
    color: rgb(30, 144, 255);
    border-radius: 5px;
    padding: 1em;
    box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
    margin-top: 30px;
    .list-item {
      list-style: none;
      padding: 10px 0;
      border-bottom: 1px solid #eee;
      display: flex;
      justify-content: space-between;
      .item-label {
        width: 80%;
      }
      .action-btn {
        width: 15%;
        button {
          margin: 0px 3px 5px;
          font-size: 12px;
          padding: 3px 7px;
        }
        .success {
          background-color: #009688;
        }
        .delete {
          background-color: #e91e63;
        }
        .reset {
          background-color: #03a9f4;
        }
      }
    }
    .list-item:last-of-type {
      border-bottom: none;
    }
    .done {
      text-decoration: line-through;
      color: #ddd;
    }
  }
}
</style>

写在最后

  • 感谢能花费自己宝贵的时间看完这篇文章的读者们。
  • 开始动手写你的todolist吧,别犹豫了~
  • 后续会继续更新vue3相关的新api,请点赞保持关注噢。

最后别忘了点赞噢~

最后别忘了点赞噢~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,699评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,124评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 167,127评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,342评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,356评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,057评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,654评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,572评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,095评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,205评论 3 339
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,343评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,015评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,704评论 3 332
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,196评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,320评论 1 271
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,690评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,348评论 2 358