【IMWeb训练营作业】Todo list

【IMWeb训练营作业】Todo list

最近参加腾讯课堂的IMWeb训练营,学习Vue.js,虽然之前已经了解过Vue.js,自己也跟着Vue.js官方教程走了一边,不过因工作上技术栈一直处于Angular.js 1.x,公司各种赶项目,然后就没深入去学习(其实就为自己的懒找借口,orz), 而在这课堂里面也学到了不少,进一步深入了解了虚拟dom,前端组件化,还有一些目前前端工程化等,废话少说,还是简单总结以下本次的Todo list;

一、涉及知识点:

  • 内置指令(v-model, v-on (缩写:‘@’),v-show,v-if, v-bind (缩写:‘:’),v-for)
  • 计算属性 computed
  • 观察 watcher
  • 自定义指令directives
  • localStorage的使用

二、简单功能任务

  • 添加任务,回车添加(v-model, v-on使用)
  • 删除任务(v-on使用)
  • 编辑任务 (自定义指令使用-directives )
  • 筛选任务 (计算属性使用-computed)
  • 展示任务(v-show,v-if, v-bind,v-for)
  • 存取数据(localStorage,观察 watcher )

三、任务核心

(一)、 目录结构

这里写图片描述

(二)、 核心文件

package.json

使用browser-sync浏览器同步测试调试,

{
    "name": "todo-list",
    "version": "1.0.0",
    "description": "todo-list demo",
    "main": "index.js",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "dev": "browser-sync start --server --files \"src/css/*.css, *.html\""
    },
    "keywords": [
        "vue"
    ],
    "author": "Hung",
    "license": "ISC",
    "dependencies": {
        "vue": "^2.2.6"
    },
    "devDependencies": {
        "browser-sync": "^2.18.8"
    }
}

index.html
基本上直接采用课堂页面结构

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="UTF-8">
    <title>Todo list</title>
    <link rel="stylesheet" href="src/css/index.css">
    <script src="./node_modules/vue/dist/vue.min.js"></script>
</head>

<body>
    <!-- top /s -->
    <div class="page-top">
        <div class="page-content">
            <h2>任务计划列表</h2>
        </div>
    </div>
    <!-- top /e -->

    <!-- main /s -->
    <div class="main">

        <h3 class="big-title">添加任务:</h3>

        <!-- task-input -->
        <input placeholder="请添加任务(提示:回车即可添加任务)" 
               class="task-input" 
               type="text" 
               v-model="todo" 
               v-on:keyup.13="addTodo" />

        <!-- task-count -->
        <ul class="task-count" v-show="list.length">
            <!-- 未完成任务 -->
            <li>{{noCheckeLength}}个任务未完成</li>

            <!-- 任务状态 -->
            <li class="action">
                <a href="#all" :class="{active:visibility === 'all'}">所有任务</a>
                <a href="#unfinished" :class="{active:visibility === 'unfinished'}">未完成的任务</a>
                <a href="#finished" :class="{active:visibility === 'finished'}">完成的任务</a>
            </li>

        </ul>

        <h3 class="big-title">任务列表:</h3>

        <!-- task -->
        <div class="tasks">
            <!-- 空数据提醒 -->
            <span class="no-task-tip" v-show="!list.length">还没有添加任何任务</span>

            <!-- todo 列表 -->
            <ul class="todo-list">
                <li class="todo" v-for="item in filteredList" :class="{completed: item.isChecked,editing: item === editorTodos}">
                    <div class="view">
                        <input class="toggle" type="checkbox" v-model="item.isChecked" />
                        <label @dblclick="editorTodo(item)">{{ item.title }}</label>
                        <button class="destroy" @click="deleteTodo(item)"></button>
                    </div>
                    <input  class="edit" 
                            type="text" 
                            v-model="item.title" 
                            v-foucs="editorTodos === item" 
                            @blur="editorTodoed(item)" 
                            @keyup.13="editorTodoed(item)" 
                            @keyup.esc="cancelTodo(item)" />
                </li>
            </ul>

        </div>
    </div>
    <!-- top /e -->

    <script src="./src/app.js"></script>
</body>

</html>

app.js

// 存取localStorage中的数据
var store = {
    // 存
    save(key, value) {
        localStorage.setItem(key, JSON.stringify(value));
    },
    // 取
    fetch(key) {
        return JSON.parse(localStorage.getItem(key)) || [];
    }
};


// 过滤情况 all finished unfinished
var filter = {
    // all--> 所有任务
    all: function(list) {
        return list;
    },
    // finished --> 完成任务
    finished: function(list) {
        return list.filter(function(item) {
            return item.isChecked;
        })
    },
    // unfinished --> 未完成任务
    unfinished: function() {
        return list.filter(function(item) {
            return !item.isChecked;
        })
    }
};

// 取出本地数据
var list = store.fetch("TODO_LIST");

var vm = new Vue({
    el: ".main", // 挂载元素
    data: {
        list: list,
        todo: "",
        editorTodos: '',
        beforeTitle: '',
        visibility: "all"
    },
    // 监测
    watch: {
        list: {
            handler: function() {
                store.save("TODO_LIST", this.list);
            },
            deep: true // 深度监测
        }
    },
    // 计算属性
    computed: {
        noCheckeLength: function() {
            return this.list.filter(function(item) {
                return !item.isChecked
            }).length
        },
        filteredList: function() {
            return filter[this.visibility] ? filter[this.visibility](list) : list;
        }
    },
    // 方法
    methods: {
        // 添加任务
        addTodo() {
            this.list.push({
                title: this.todo,
                isChecked: false
            });
            this.todo = '';

        },
        // 删除任务
        deleteTodo(todo) {
            var index = this.list.indexOf(todo);
            this.list.splice(index, 1);
        },
        // 编辑任务
        editorTodo(todo) {
            this.beforeTitle = todo.title;
            this.editorTodos = todo;
        },
        // 编辑任务成功
        editorTodoed(todo) {
            this.editorTodos = '';
        },
        // 取消编辑任务
        cancelTodo(todo) {
            todo.title = this.beforeTitle;
            this.beforeTitle = '';
            this.editorTodos = '';
        }
    },
    // 指令
    directives: {
        "foucs": {
            // 钩子函数,el为元素,binding是表达式的值
            update(el, binding) {
                if (binding.value) {
                    el.focus();
                }
            }
        }
    }
});

// 获取hash --> 得到显示数据属性状态
function watchHashChange() {
    var hash = window.location.hash.slice(1);
    vm.visibility = hash;
}

watchHashChange();

window.addEventListener("hashchange", watchHashChange);

index.css
直接引入课堂样式

body{margin:0;background-color:#fafafa;font:14px 'Helvetica Neue',Helvetica,Arial,sans-serif}
h2{margin:0;font-size:12px}
a{color:#000;text-decoration:none}
input{outline:0}
button{margin:0;padding:0;border:0;background:0 0;font-size:100%;vertical-align:baseline;font-family:inherit;font-weight:inherit;color:inherit;outline:0}
ul{padding:0;margin:0;list-style:none}
.page-top{width:100%;height:40px;background-color:#db4c3f}
.page-content{width:50%;margin:0 auto}
.page-content h2{line-height:40px;font-size:18px;color:#fff}
.main{width:50%;margin:0 auto;box-sizing:border-box}
.task-input{width:99%;height:30px;outline:0;border:1px solid #ccc}
.task-count{display:flex;margin:10px 0}
.task-count li{padding-left:10px;flex:1;color:#dd4b39}
.task-count li:nth-child(1){padding:5px 0 0 10px}
.action{text-align:center;display:flex}
.action a{margin:0 10px;flex:1;padding:5px 0;color:#777}
.action a:nth-child(3){margin-right:0}
.active{border:1px solid rgba(175,47,47,.2)}
.tasks{background-color:#fff}
.no-task-tip{padding:10px 0 10px 10px;display:block;border-bottom:1px solid #ededed;color:#777}
.big-title{color:#222}
.todo-list{margin:0;padding:0;list-style:none}
.todo-list li{position:relative;font-size:16px;border-bottom:1px solid #ededed}
.todo-list li:hover{background-color:#fafafa}
.todo-list li.editing{border-bottom:none;padding:0}
.todo-list li.editing .edit{display:block;width:506px;padding:13px 17px 12px 17px;margin:0 0 0 43px}
.todo-list li.editing .view{display:none}
.todo-list li .toggle{text-align:center;width:40px;height:auto;position:absolute;top:5px;bottom:0;margin:auto 0;border:none;-webkit-appearance:none;appearance:none}
.toggle{text-align:center;width:40px;height:auto;position:absolute;top:5px;bottom:0;margin:auto 0;border:none;-webkit-appearance:none;appearance:none}
.toggle:after{content:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="40" fill="none" stroke="#ededed" stroke-width="3"/></svg>')}
.toggle:checked:after{content:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="40" fill="none" stroke="#bddad5" stroke-width="3"/><path fill="#5dc2af" d="M72 25L42 71 27 56l-4 4 20 20 34-52z"/></svg>')}
.todo-list li label{white-space:pre-line;word-break:break-all;padding:15px 60px 15px 15px;margin-left:45px;display:block;line-height:1.2;transition:color .4s}
.todo-list li.completed label{color:#d9d9d9;text-decoration:line-through}
.todo-list li .destroy{display:none;position:absolute;top:0;right:10px;bottom:0;width:40px;height:40px;margin:auto 0;font-size:30px;color:#cc9a9a;margin-bottom:11px;transition:color .2s ease-out}
.todo-list li .destroy:hover{color:#af5b5e}
.todo-list li .destroy:after{content:'×'}
.todo-list li:hover .destroy{display:block}
.todo-list li .edit{display:none}
.todo-list li.editing:last-child{margin-bottom:-1px}

四、展示

所有任务
这里写图片描述

未完成任务
这里写图片描述

完成任务
这里写图片描述

五、小结

本次的Todo list 为经典的入门练习,基本能通过这来掌握一些基本的指令和语法,同时, 对于接触过Angular.js总体来说,很多地方是比较相似的,这从内置的指令和一些语法可以看得出,但是Vue.js 更加灵活,毕竟Vue.js 借鉴了Angular.js和React.js,当然也少不了官网教程、文档的友好。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Node.js中,你可以使用内置的crypto模块来实现HMAC-SHA256算法。下面是一个示例代码: ```javascript const crypto = require('crypto'); const secret = 'Secret_Key'; const message = 'timestampGET/users/self/verify'; const hmac = crypto.createHmac('sha256', secret); hmac.update(message); const sign = hmac.digest('base64'); console.log(sign); ``` 在这个示例中,我们首先引入了crypto模块。然后,我们定义了密钥(secret)和要加密的消息(message)。接下来,我们使用createHmac方法创建了一个HMAC对象,并指定了算法为SHA256,并传入密钥。然后,我们使用update方法将消息传入HMAC对象进行更新。最后,我们使用digest方法以base64编码格式输出加密后的签名。 请注意,这个示例中的密钥和消息只是示意用法,你需要根据实际情况替换为你自己的密钥和消息。 #### 引用[.reference_title] - *1* [Typescript/Nodejs 使用HmacSHA256 & Base64对接口调用签名](https://blog.csdn.net/HumorChen99/article/details/117548951)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v4^insert_chatgpt"}} ] [.reference_item] - *2* [Hmac SHA256 加密在原生 Java 及 Node.js 的实现](https://blog.csdn.net/frgod/article/details/122025192)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v4^insert_chatgpt"}} ] [.reference_item] - *3* [腾讯IMWeb团队是如何使用 NodeJS 实现 JWT 原理](https://blog.csdn.net/lunahaijiao/article/details/109881868)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v4^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值