vue 3 项目实战一(绘制登录界面)
目录
一、概述
二、创建vue项目
三、需求分析
四、构建组件
五、vue组件之间的通信
一、概述
本文记录了项目实现的详细步骤以及原理,十分适合初学vue的萌新练手,也是阶段性学习的一个总结,可能会有些啰嗦,勿怪~。
先从登录界面开始,常规的登录界面不太好看,起不到复习巩固的作用,于是找到了下面这个
源码:
https://codepen.io/ricardoolivaalonso/pen/YzyaRPNhttps://codepen.io/ricardoolivaalonso/pen/YzyaRPN下面将其拆解并封装,相当于化简为繁,将原本的html+css+js 项目转变为了vue项目,拆分成了三个组件。过程比较详细且啰嗦,选择性观看即可。
二、创建vue项目
1、vue create project_name
2、相关配置
3、cd project_name
4、code . //快捷打开vscode
Typescript 是JavaScript的超集,Typescript语法在执行是会先转成JavaScript,在使用时如果不习惯ts可以转 js语法 <script setup lang="js"> 。
项目结构:
三、需求分析
运行源代码可以发现,页面可分为三个主要部分:
因此将这三个部分封装成组件 ,在src下新建login文件夹,用于单独存放该项目的一些文件
进行一些初始化、将 router/index.ts 路由改写
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'const routes: Array<RouteRecordRaw> = [{ path: '/', component: () => import('@/login/login.vue') },
]const router = createRouter({history: createWebHashHistory(),routes
})export default router
简单测试一下
四、构建组件
4.1、背景组件,也是该登录界面的父组件
login/login.vue 文件代码
<template><div class="body"><div class="main">adad</div></div>
</template><script setup lang="ts"></script><style scoped >
*, *::after, *::before {margin: 0;padding: 0;box-sizing: border-box;user-select: none;}.body {width: 100%;height: 100vh;display: flex;justify-content: center;align-items: center;font-family: "Montserrat", sans-serif;font-size: 12px;background-color: #ecf0f3;color: #a0a5a8;}.main {position: relative;width: 1000px;min-width: 1000px;min-height: 600px;height: 600px;padding: 25px;background-color: #ecf0f3;box-shadow: 10px 10px 10px #d1d9e6, -10px -10px 10px #f9f9f9;border-radius: 20px;overflow: hidden;}@media (max-width: 1200px) {.main {transform: scale(0.7);}}@media (max-width: 1000px) {.main {transform: scale(0.6);}}@media (max-width: 800px) {.main {transform: scale(0.5);}}@media (max-width: 600px) {.main {transform: scale(0.4);}}
</style>
零碎笔记:
1.css盒子模型
即元素可以看成一个盒子,即拥有margin、border、padding、content四个属性
2.css的伪类和伪元素
伪类:为处于某个状态的已有元素添加对应的样式,(项目的切换按钮用到了伪类),例如
- 设置鼠标悬停在元素上时的样式 :hover
- 为已访问和未访问链接设置不同的样式 :link :visited
- 设置元素获得焦点时的样式 :focus
注意:如果同时作用在一个元素上,有书写顺序,比如对a标签进行操作:
a:link -> a:visited -> a:hover -> a:active
伪元素: 由“ :: ” 表示,创建一些不在文档树中的元素,并为其添加样式
- ::after 在每个 元素之后插入内容。
- ::befor 在每个元素之前插入内容。
3、元素定位:遵从 “ 子绝父相 ”
4.2、switch组件
点击可实现滑动效果
分析
代码
<template>
<div class="switch" id="switch-cnt"><div class="switch__circle"></div><div class="switch__circle switch__circle--t"></div><div class="switch__container" id="switch-c1"><h2 class="switch__title title">Welcome Back !</h2><p class="switch__description description">To keep connected with us please login with your personal info</p><button class="switch__button button switch-btn" @click="change">SIGN IN</button></div><div class="switch__container is-hidden" id="switch-c2"><h2 class="switch__title title">Hello Friend !</h2><p class="switch__description description">Enter your personal details and start journey with us</p><button class="switch__button button switch-btn" @click="change">SIGN UP</button></div></div>
</template><script setup lang="ts">const change = () => {const switchC1 = document.querySelector("#switch-c1") as any;const switchC2 = document.querySelector("#switch-c2") as any;const switchCircle = document.querySelectorAll(".switch__circle") as any;const switchCtn = document.querySelector("#switch-cnt") as any; switchCtn.classList.add("is-gx");setTimeout(function(){switchCtn.classList.remove("is-gx");}, 1500)switchCtn.classList.toggle("is-txr");switchCircle[0].classList.toggle("is-txr");switchCircle[1].classList.toggle("is-txr");switchC1.classList.toggle("is-hidden");switchC2.classList.toggle("is-hidden");}
</script><style scoped>
@import './login.css';
/*
将源码中的css样式单独存放,在各组件中导入就可以。
后续整理代码时建议,将全局样式和局部样式分开。
*/
</style>
部分css样式
实现隐藏
隐藏元素的几种方法:opacity: 0、visibility: hidden、display: none
移动主要是靠设置 left 偏移得到的
移动过程中的动画
4.3、sign组件
两者结构部分
<!-- sign_up -->
<template><div class="container a-container" id="a-container"><form class="form" id="a-form" method="" action=""><h2 class="form_title title">Create Account</h2><div class="form__icons"><img class="form__icon" src=" "><img class="form__icon" src=" "><img class="form__icon" src=" "></div><span class="form__span">or use email for registration</span><input class="form__input" type="text" placeholder="Name"><input class="form__input" type="text" placeholder="Email"><input class="form__input" type="password" placeholder="Password"><button class="form__button button submit">SIGN UP</button></form></div>
</template>
<style scoped>
@import './login.css';
/* 将源码中的css样式单独存放,在各组件中导入就可以。*/
</style>
<!-- sign_in -->
<template>
<div class="container b-container" id="b-container"><form class="form" id="b-form" method="" action=""><h2 class="form_title title">Sign in to Website</h2><div class="form__icons"><img class="form__icon" src=" "><img class="form__icon" src=" "><img class="form__icon" src=" "></div><span class="form__span">or use your email account</span><input class="form__input" type="text" placeholder="用户名" v-model="loginFrom.username"><input class="form__input" type="password" placeholder="密码" v-model.lazy="loginFrom.password"><a class="form__link">Forgot your password?</a><button class="form__button button submit">SIGN IN</button></form>
</div>
</template>
<style scoped>
@import './login.css';
/* 将源码中的css样式单独存放,在各组件中导入就可以。*/
</style>
像组件中如facebook的小图标,利用base64 将图片转为字符串以此来代替src的位置,可以减少http请求。 (base64推荐小图标使用,jpg转base64,体积会变大一点点。)
也可以使用矢量图:iconfont-阿里巴巴矢量图标库
组件的移动和switch类似,多了个 z-index 来对这两个组件进行了堆叠
五、vue组件之间的通信
现在各组件已经构建好了,但想要让switch子组件的按钮事件,也能控制到sign_in/sign_up子组件,则需要借助 Event Bus(用其它的方式也行,比如vuex )。 常用的父子组件通讯方式有:props,$emit ,$ref 等。
Event Bus:就是A-->B 有困难,那么就借助全局C来传数据,A-->C-->B
Vue3中需要借助 mitt 组件库来完成
1、安装:npm i mitt
2、在main中声明
// main.ts import { createApp } from 'vue' import App from './App.vue' import router from './router' import mitt from 'mitt'const app=createApp(App) app.config.globalProperties.emitter = mitt()app.use(router) app.mount('#app')
3、新建文件、进封装
// src/hooks/useEmitter.js import { getCurrentInstance } from 'vue'export default function useEmitter() {const internalInstance = getCurrentInstance()const emitter = internalInstance.appContext.config.globalProperties.emitterreturn emitter }
5.1、在switch组件中添加部分代码
<script setup lang="ts">import { ref } from 'vue'import useEmitter from '@/hooks/useEmitter.js'const sidebarOpen = ref(true)const emitter = useEmitter()const change = () => {const switchC1 = document.querySelector("#switch-c1") as any;const switchC2 = document.querySelector("#switch-c2") as any;const switchCircle = document.querySelectorAll(".switch__circle") as any;const switchCtn = document.querySelector("#switch-cnt") as any;switchCtn.classList.add("is-gx");setTimeout(function(){switchCtn.classList.remove("is-gx");}, 1500)switchCtn.classList.toggle("is-txr");switchCircle[0].classList.toggle("is-txr");switchCircle[1].classList.toggle("is-txr");switchC1.classList.toggle("is-hidden");switchC2.classList.toggle("is-hidden");sidebarOpen.value = !sidebarOpen.valueemitter.emit('change', sidebarOpen.value)}
</script>
vscode中可能会有错误提示,用的语法是ts的,导入自定义js时会检查其类型。
取消检查==>
修改tsconfig.json中的compilerOptions,将"allowJs"设为true,没有则自行添加
5.2、sign_in/sign_up内添加:
<script setup lang="ts">import { ref, onMounted } from 'vue'import useEmitter from '@/hooks/useEmitter.js'// const isOpen = ref(true)const emitter = useEmitter()onMounted(() => {emitter.on('change', (isOpen : boolean) => {watch: {isOpen:{let aContainer = document.querySelector("#a-container") as any;aContainer.classList.toggle("is-txl");//b中样式// let bContainer = document.querySelector("#b-container") as any;// bContainer.classList.toggle("is-txl");// bContainer.classList.toggle("is-z200");}}})})</script>
到这边样式部分基本完毕了,存在什么问题、遗漏,请多多交流,帮帮本萌新,之后会对登录、注册的功能进行实现。
vue 3 项目实战二(实现登录、注册)_咔卡熊的博客-CSDN博客
vue 3 项目实战一(绘制登录界面)相关推荐
- python项目实战:pyqt5实现登录界面模板
2019独角兽企业重金招聘Python工程师标准>>> 前言 今天为大家介绍一个利用开发登录界面模板,基于pyqt5库,pyqt5这也一个PythonGUI界面开发的库,非常强大,关 ...
- vue.js项目实战运用篇之抖音视频APP-第十一节: 注册登录及验证码功能
[温馨提示]:若想了解更多关于本次项目实战内容,可转至vue.js项目实战运用篇之抖音视频APP-项目规划中进一步了解项目规划. [项目地址] 项目采用Git进行管理,最终项目将会发布到GitHub中 ...
- vue.js项目实战运用篇之抖音视频APP-第三节:底部导航栏组件功能
[温馨提示]:若想了解更多关于本次项目实战内容,可转至vue.js项目实战运用篇之抖音视频APP-项目规划中进一步了解项目规划. [项目地址] 项目采用Git进行管理,最终项目将会发布到GitHub中 ...
- vue.js项目实战运用篇之抖音视频APP-第二节:项目基础架构搭建
[温馨提示]:若想了解更多关于本次项目实战内容,可转至vue.js项目实战运用篇之抖音视频APP-项目规划中进一步了解项目规划. [项目地址] 项目采用Git进行管理,最终项目将会发布到GitHub中 ...
- Vue ts 项目实战
Vue ts 项目实战 首先,没装vue-cli的,可以使用下列任一命令安装这个新的包: npm install -g @vue/cli # OR yarn global add @vue/cli 安 ...
- vue+element ui实现好看的登录界面
闲暇之余使用vue+element ui制作了个登录界面 话不多说,先上图 界面效果图 下面直接上代码: <template><div class="loginbody&q ...
- Vue + Element-UI —— 项目实战(零)(项目概述)
Vue + ElementUI 后台管理项目实战 内容 参考链接 一 Vue + Element-UI -- 项目实战(零)(项目概述[附源码]) 二 Vue + Element-UI -- 项目实战 ...
- vue.js项目实战运用篇之抖音视频APP-第八节: 视频播放功能
[温馨提示]:若想了解更多关于本次项目实战内容,可转至vue.js项目实战运用篇之抖音视频APP-项目规划中进一步了解项目规划. [项目地址] 项目采用Git进行管理,最终项目将会发布到GitHub中 ...
- vue.js项目实战运用篇之抖音视频APP-第一节:项目环境搭建
[温馨提示]:若想了解更多关于本次项目实战内容,可转至vue.js项目实战运用篇之抖音视频APP-项目规划中进一步了解项目规划. [项目地址] 项目采用Git进行管理,最终项目将会发布到GitHub中 ...
最新文章
- MATLAB从入门到精通-新增返回数组高、宽数字特征的全新方式
- 经验|博士毕业,也写一些发文章的心得
- Entity Framework Core 执行SQL语句和存储过程
- 清华男神再获世界大奖,从放牛娃到清华校长,他考研3次,读博7年,做出诺奖级的科研成果...
- OpenCV 3.1 imwrite()函数写入异常问题解决方法
- docker build no such file or directory
- Tensorflow报错_np_qint8 = np.dtype([(“qint8“, np.int8, 1)])
- 01-操作数组的方法
- MySQL多线程备份工具mydumper
- API之实用工具Postman 使用方法
- MySQL客户端工具的选择
- linux yum 五笔输入法,CentOS 7 安装五笔输入法
- Entry name ‘res/layout/test_toolbar.xml‘ collided
- python 全栈开发,Day104(DRF用户认证,结算中心,django-redis)
- PAT_乙级_1007_筱筱
- oracle数据库直方图,[转] oracle统计信息(statistics)和直方图(histogram)
- Profinet协议基础知识(三)
- [华为 HCNA ] VLAN的介绍和划分
- 静心,多听,善思--学习之道也
- 先别急着练速写,人物慢写才是第一步
热门文章
- DataGrid梆定DroDownList
- 狂暴者 pat basic 练习二十九 旧键盘
- 蓝牙耳机超长续航哪个牌子好?长续航时间的无线耳机推荐!
- Prim算法(matlab实现)
- 高德地图驾车路径规划API,获取两地点之间的驾车里程和时间
- 【LeetCode刷题】374. 猜数字大小
- Survivor区放不下存活对象,那么存活对象直接就分配到老年代?
- NYOJ 整数划分(三) (划分数大集合)
- 体验 IntelliJ IDEA 2021.1 Run Targets 远程环境调试程序
- 火星人培训python