【JS】[Vue笔记] 仿照`Teambition`手写`task-panel` ---- 组件篇

Introduction

【JS】[Vue笔记] 仿照`Teambition`手写`task-panel` ---- 组件篇
今天小试牛刀,试着写一个task-panel,不过涉及的组件有点多,先写好组件部分,再把他们拼装成task-panel

设计需求

结构说明

  1. 组件由三个div模块组成,分别为head, operatorcard-grid

  2. head由标题,任务个数,和一个dropdown组件构成

  3. operator由一个长条按钮creator和编辑框editor组成,这两个部分不能同时存在

  4. card-grid由两种卡片组成,一种是未完成的,一种是已完成的

组件说明

dropdown

dropdown包含三个操作,

  • 修改task-panel的标题
  • 在此task-panel后新增一个task-panel

  • 删除此task-panel

注意这个组件与父组件相关联

creator

creator的功能是显示editor编辑框,同时自身消失

editor

editor提供两种按钮,取消与 确定,在其中输入文本后传递给父组件

card

card代表一项任务

组件实现

dropdown

在组件中,需要为每个menu-item设置好:text, :action@click事件绑定
其中action是为了统一@click处理的方式,不然menu-item多了,要为每个组件绑定一个不同的处理函数,详细请看下方行为处理

设计需求

  1. 主要功能

    • 显示一个菜单,这个菜单有三个功能,分别是

      • 修改task-panel的标题
      • 在此task-panel后新增一个task-panel

      • 删除此task-panel

    • 这三个功能通过emit传递给父组件

  2. 组件修饰

    • 鼠标悬浮div.entry的图标时,图标的颜色加深

  3. 接口

    • 通过active属性控制菜单的显示

[active == false] 初始状态

    <div class="entry" @click="toggleHandler">

<svg t="1608216593558" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3281" width="48" height="48"><path d="M110.336 572.330667a85.333333 85.333333 0 1 0 120.661333-120.661334 85.333333 85.333333 0 0 0-120.661333 120.661334zM451.669333 572.330667a85.333333 85.333333 0 1 0 120.661334-120.661334 85.333333 85.333333 0 0 0-120.661334 120.661334zM793.002667 572.330667a85.333333 85.333333 0 1 0 120.661333-120.661334 85.333333 85.333333 0 0 0-120.661333 120.661334z" p-id="3282"></path></svg>

</div>

[active == true] 激活状态

【JS】[Vue笔记] 仿照`Teambition`手写`task-panel` ---- 组件篇

    <div class="menu" v-show="active">

<menu-item text="edit" action="edit" @click="handler">

<svg class="icon" viewBox="0 0 1024 1024">

<path d="M856.576 290.304l-63.488 63.488-122.88-122.88 63.488-63.488a11.776 11.776 0 0 1 8.704-3.584 11.264 11.264 0 0 1 8.704 3.584l105.472 105.472a12.8 12.8 0 0 1 0 17.408zM208.896 716.8L307.2 815.616l-131.584 32.768 33.28-131.584z m153.6 65.536l-122.88-120.832 387.072-387.072 122.88 122.368-388.096 386.56z m537.6-552.96l-105.472-105.472a74.24 74.24 0 0 0-102.4 0L174.592 640a68.608 68.608 0 0 0-18.432 32.256L102.4 883.2a31.744 31.744 0 0 0 8.192 29.696 30.208 30.208 0 0 0 22.528 8.704h7.68l210.944-51.2a66.048 66.048 0 0 0 32.256-18.432L900.096 333.824a74.24 74.24 0 0 0 0-102.4z"></path>

</svg>

</menu-item>

<menu-item text="add" action="add" @click="handler">

<svg class="icon" viewBox="0 0 1024 1024">

<path d="M476.16 476.16V191.0272c0-20.6848 16.0256-37.4272 35.84-37.4272 19.8144 0 35.84 16.7424 35.84 37.4272V476.16h285.1328c20.6848 0 37.4272 16.0256 37.4272 35.84 0 19.8144-16.7424 35.84-37.4272 35.84H547.84v285.1328c0 20.6848-16.0256 37.4272-35.84 37.4272-19.8144 0-35.84-16.7424-35.84-37.4272V547.84H191.0272C170.3424 547.84 153.6 531.8144 153.6 512c0-19.8144 16.7424-35.84 37.4272-35.84H476.16z"></path>

</svg>

</menu-item>

<menu-item text="delete" action="delete" @click="handler">

<svg class="icon" viewBox="0 0 1024 1024">

<path d="M890.88 241.9712h-230.2976V202.752c0-55.296-45.056-100.352-100.352-100.352H463.7696c-55.3472 0-100.352 45.056-100.352 100.352v39.2192H133.12a30.72 30.72 0 0 0 0 61.4912h66.3552L296.2432 855.04c2.56 14.6944 15.3088 25.3952 30.2592 25.3952h370.9952a30.72 30.72 0 0 0 30.2592-25.3952l96.768-551.5776H890.88a30.72 30.72 0 0 0 0-61.4912M261.8368 303.4624h103.68l37.2224 515.584h-50.432L261.8368 303.4624m202.496 515.584l-37.1712-515.584h169.6768l-37.1712 515.584H464.3328m207.36 0h-50.432l37.1712-515.584h103.7312l-90.4704 515.584M463.7696 163.8912h96.4608c21.4528 0 38.912 17.408 38.912 38.8608v39.2192H424.8576V202.752a38.912 38.912 0 0 1 38.912-38.8608"></path>

</svg>

</menu-item>

</div>

[行为1] 点击初始状态下的dropdown

方法 toggleHandler

    toggleHandler() {

this.$emit('toggle')

},

[行为2] 点击菜单中的条目

    handler(action) {

this.$emit('toggle-menu', action)

}

组件修饰 <style scoped>

.entry svg.icon:hover {

opacity: 1;

cursor: pointer;

}

// 图标设置

.entry svg.icon {

width: 1em;

height: 1em;

opacity: 0.5;

}

// 设置为相对布局,这样整个菜单的显示以这个为参照

.entry svg.icon {

position: relative;

}

// 菜单栏

div.menu {

/* border: 1px solid black; */

box-shadow: 0 12px 32px 0 rgba(38,38,38,0.16);

border-radius: 4px;

background-color: white;

width: 194px;

position: absolute;

top: 31.5px;

}

// 整体布局

div.dropdown {

display: flex;

flex-direction: column;

align-items: center;

}

creator

【JS】[Vue笔记] 仿照`Teambition`手写`task-panel` ---- 组件篇

设计需求

  1. 主要功能

    • 点击后使editor组件显示,同时自身消失,此时active == true

    • 当退出editor时,creator恢复,此时active == false

  2. 组件修饰

    • 鼠标悬浮时,box-shadow颜色加深,内置图标变蓝

  3. 接口设计

    • active控制editor的显示

基本结构

  <div class="creator"

v-show='!active'

@click="handler">

<svg id="at-plus" viewBox="0 0 1024 1024">

<path d="M476.16 476.16V191.0272c0-20.6848 16.0256-37.4272 35.84-37.4272 19.8144 0 35.84 16.7424 35.84 37.4272V476.16h285.1328c20.6848 0 37.4272 16.0256 37.4272 35.84 0 19.8144-16.7424 35.84-37.4272 35.84H547.84v285.1328c0 20.6848-16.0256 37.4272-35.84 37.4272-19.8144 0-35.84-16.7424-35.84-37.4272V547.84H191.0272C170.3424 547.84 153.6 531.8144 153.6 512c0-19.8144 16.7424-35.84 37.4272-35.84H476.16z">

</path>

</svg>

</div>

[行为] 处理点击事件

    handler() {

this.$emit('toggle')

},

组件修饰 <style scoped>

// icon

.creator svg {

width: 20px;

height: 20px;

color: #8C8C8C;

}

</style>

// 整体布局

div.creator {

height: 30px;

box-shadow: 0 1px 2px rgba(0,0,0,0.1);

border-radius: 4px;

display: flex;

align-items: center;

justify-content: center;

/* text-align: center; */

background-color: white;

margin: 8px 0;

}

// 鼠标悬浮

div.creator:hover {

box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);

cursor: pointer;

}

div.creator:hover svg#at-plus path {

fill: #309fee;

}

editor

【JS】[Vue笔记] 仿照`Teambition`手写`task-panel` ---- 组件篇
_
【JS】[Vue笔记] 仿照`Teambition`手写`task-panel` ---- 组件篇

设计需求

  1. 主要功能

    • 提供输入文本框和两个按钮控制
    • 将输入的文本传递给父组件

  2. 组件修饰

    • 针对textarea标签,鼠标点击进入时,边框变为蓝色
    • 对两个button按钮背景颜色和文字颜色进行设置
    • 鼠标悬浮在button上时,需要button变换背景色,也可以使用transition属性添加动画

  3. 接口设计

    • holder控制textareaplaceholder的内容

    • rows 控制textarearows属性大小

    • active控制自身的显示,v-show="active"

基本结构

  <div class="editor" v-show="active">

<div class="body">

<textarea

@keyup.enter="submitEditorText"

v-model="inputText"

:placeholder="holder"

data-real="true"

:rows="rows">

</textarea>

</div>

<div class="footer">

<button class="cancel" @click="cancelHandler">

<span class="next-btn">取消</span>

</button>

<button class="submit" :disable="inputText.length == 0"

@click="submitEditorText">

<span class="next-btn">确定</span>

</button>

</div>

</div>

组件修饰 <style scoped>

  1. 主要样式

.footer button.cancel {

color: #1b9aee;

border-color: #ccecff;

background-color: transparent;

}

.footer button.cancel:hover {

color: #1b9aee;

background-color: #f2fbff;

border-color: #ccecff;

cursor: pointer;

}

.footer button.submit {

margin-left: 12px;

border-style: solid;

background-color: #1b9aee;

border-color: transparent;

color: rgb(255, 255, 255);

}

.footer button.submit:hover {

cursor: pointer;

background-color: #0171c2;

}

.footer button.submit[disabled] {

cursor: not-allowed;

background-color: #bfbfbf;

border-color: #bfbfbf;

}

  1. 次要样式

.editor {

width: 100%;

/* height: 216px; */

background-color: #fff;

box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.1);

}

// textarea

textarea {

color: #262626;

/* padding: 4px 8px; */

font-size: 14px;

font-weight: 400;

outline: none;

border-radius: 4px;

border: none;

line-height: 20px;

resize: vertical;

vertical-align: middle;

/* width: 230px; */

width: 95%;

height: 60px;

padding: 4px 8px;

}

textarea {

line-height: 1;

vertical-align: middle;

border: 1px solid #d9d9d9;

}

textarea:focus {

border-color: #1b9aee;

}

// 设置 position与display

.editor .body {

padding: 12px 12px 16px 12px;

display: flex;

justify-content: center;

}

// footer

.footer {

padding: 12px;

text-align: right;

border-top: 1px solid #E5E5E5;

}

// 通用button样式

.footer button {

border-style: solid;

border-radius: 4px;

padding: 0 7px;

height: 28px;

line-height: 26px;

font-size: 14px;

border-width: 1px;

min-width: 52px;

display: inline-block;

text-align: center;

white-space: nowrap;

vertical-align: middle;

transition: background-color 0.3s ease,color 0.3s ease,border-color 0.3s ease;

}

行为设计

    submitEditorText() {

this.$emit('submit', this.inputText)

this.inputText = ''

},

cancelHandler() {

this.$emit('cancel')

},

card

【JS】[Vue笔记] 仿照`Teambition`手写`task-panel` ---- 组件篇

设计需求

  1. 主要功能

    • 显示任务的状态与任务的描述
    • 在组件中,通过点击span.check-box图标来控制任务的状态
    • 不提供细节服务

  2. 组件修饰

    • done == 'true'时,card整体变灰

      • 同时span.check-box打勾
      • 同时横线穿过card的文字内容

    • 鼠标悬浮时

      • box-shadow变深

      • 整体向下偏移一点
      • 同时用动画修饰这些变化

  3. 接口设计

    • done表示card的状态,<div class="card" :class="{'done': done}">

    • content表示card的任务内容

基本结构

  <div class="card" :class="{'done': done}">

<span class="check-box" @click="toggleHandler">

<svg viewBox="0 0 1024 1024">

<path v-show="!done" d="M804.5568 102.4H219.4432A117.3504 117.3504 0 0 0 102.4 219.4432v585.1136A117.3504 117.3504 0 0 0 219.4432 921.6h585.1136A117.3504 117.3504 0 0 0 921.6 804.5568V219.4432A117.3504 117.3504 0 0 0 804.5568 102.4m0 70.1952c25.3952 0 46.848 21.4528 46.848 46.848v585.1136a47.4112 47.4112 0 0 1-46.848 46.848H219.4432a47.4112 47.4112 0 0 1-46.848-46.848V219.4432c0-25.3952 21.4528-46.848 46.848-46.848h585.1136">

</path>

<path v-show="done" d="M804.5568 102.4H219.4432A117.3504 117.3504 0 0 0 102.4 219.4432v585.1136A117.3504 117.3504 0 0 0 219.4432 921.6h585.1136A117.3504 117.3504 0 0 0 921.6 804.5568V219.4432A117.3504 117.3504 0 0 0 804.5568 102.4m0 70.1952c25.3952 0 46.848 21.4528 46.848 46.848v585.1136a47.4112 47.4112 0 0 1-46.848 46.848H219.4432a47.4112 47.4112 0 0 1-46.848-46.848V219.4432c0-25.3952 21.4528-46.848 46.848-46.848h585.1136M449.024 683.6736a34.9184 34.9184 0 0 1-24.7808-10.2912L276.992 526.2336a35.1744 35.1744 0 0 1 49.664-49.664l122.368 122.3168 248.1664-248.2176a35.072 35.072 0 1 1 49.664 49.6128l-273.0496 273.1008a34.9184 34.9184 0 0 1-24.832 10.24">

</path>

</svg>

</span>

<span class="task-content">

{{ content }}

</span>

</div>

行为设计

    toggleHandler() {

this.$emit('toggle', this.done)

},

组件修饰 <style scoped>

  1. 主要部分

/* when card is done */

.card.done .task-content {

color: rgb(140, 140, 140);

text-decoration: line-through;

}

.card.done .check-box {

fill: rgb(140, 140, 140);

}

.card:hover {

box-shadow: 0 1px 2px 2px rgba(0, 0, 0, 0.1);

transform: translateY(2px);

cursor: pointer;

}

.check-box:hover svg {

fill: #595959;

}

  1. 次要部分

.card {

display: flex;

align-items: center;

font-size: 14px;

height: 48px;

}

.card span.check-box {

width: 20px;

height: 20px;

margin: 0 12px;

}

// style of task content

/* structure of task content */

.task-content {

max-width: 172px;

font-size: 14px;

line-height: 20px;

}

/* display of task content */

.task-content {

display: flex;

flex-grow: 1;

flex-shrink: 1;

}

// whole card color

.card {

box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.1);

background-color: white;

border-radius: 4px;

transition: transform 0.2s;

}

// last: distance of each card

.card {

margin-bottom: 8px;

}

以上是 【JS】[Vue笔记] 仿照`Teambition`手写`task-panel` ---- 组件篇 的全部内容, 来源链接: utcz.com/a/87243.html

回到顶部