github地址 ,本来是个停车场实训项目,自己在上面又加了点内容 介绍地址
总体
同时也实现了比较普通的响应式布局,配合媒体查询和flex实现。
弹出框
这个弹出框的遮罩实现有问题,看源代码感觉是插入body里面,而我是直接插入到这个fixed的盒子上面,样式直接照搬element-ui的,vue的动画效果也直接搬运源代码,自己写的动画有点烂。
<template>
<transition name="dialog-fade">
<div
class="el-dialog__wrapper"
v-show="visible"
>
<div
ref="dialog"
class="el-dialog"
:class="[{ 'is-fullscreen': fullscreen, 'el-dialog--center': center }]"
:style="style"
>
<div class="el-dialog__header">
<slot name="title">
<span class="el-dialog__title">{{ title }}</span>
</slot>
<button
type="button"
class="el-dialog__headerbtn"
aria-label="Close"
v-if="showClose"
@click="handleClose">
<i class="el-dialog__close el-icon el-icon-close"></i>
</button>
</div>
<div class="el-dialog__body"><slot></slot></div>
<div class="el-dialog__footer"><slot name="footer"></slot></div>
</div>
<!-- 暂时把点击事件移到遮罩上面 -->
<div class="v-modal" @click.self="handleWrapperClick"></div>
</div>
</transition>
</template>
<script >
export default {
name: "FanDialog",
props: {
title: {
type: String,
default: "",
},
// modal 是否需要遮罩层
modal: {
type: Boolean,
default: true,
},
// close-on-press-escape 是否可以通过按下 ESC 关闭 Dialog
closeOnPressEscape: {
type: Boolean,
default: true
},
// close-on-click-modal 是否可以通过点击 modal 关闭 Dialog
closeOnClickModal: {
type: Boolean,
default: true,
},
// fullscreen 是否为全屏 Dialog
fullscreen: Boolean,
//是否居中
center: {
type: Boolean,
default: false,
},
//关闭前的回调,会暂停 Dialog 的关闭
beforeClose: Function,
// show-close 是否显示关闭按钮
showClose: {
type: Boolean,
default: true,
},
// width Dialog 的宽度
width: {
type:String,
},
//双向绑定
visible: {
type: Boolean,
default: true,
},
// top Dialog CSS 中的 margin-top 值
top: {
type: String,
default: "15vh",
},
},
data() {
return {
closed: false
}
},
watch:{
visible(val){
this.closed=val
console.log(val);
}
},
computed: {
style() {
let style = {};
if (!this.fullscreen) {
style.marginTop = this.top;
if (this.width) {
style.width = this.width;
}
}
return style;
}
},
methods: {
// 点击dialog自身
handleWrapperClick() {
//是否开启可以点击外界区域关闭
if (!this.closeOnClickModal) return;
this.handleClose();
},
// 关闭dialog
handleClose() {
//如果有回调函数 先执行回调函数
if(typeof this.beforeClose=='function')
{
this.beforeClose(this.hide())
}else{
this.hide();
}
},
// 隐藏dialog
hide() {
this.$emit("update:visible", false);
},
},
destroyed(){
console.log('我被摧毁了');
}
};
</script >
输入框
挺多功能没实现,写的时候把理解且自己能够完全实现的功能先完成了
v-model 的组件就是@input 事件实现双向绑定,键入值就会触发。
这个组件主要自己要知道输入框的原生事件
<template>
<div
class="fan_input"
>
<template>
<input
class="input_defalut"
ref="input"
:class="[
{
'is-disabled':disabled
}
]"
:disabled="inputdisabled"
v-bind="$attrs"
v-bind:value="value"
:readonly="readonly"
@input="handleInput"
@focus="handleFocus"
@blur="handleFBlur"
>
</template>
</div>
</template>
<script>
export default {
name:'FanInput',
props: {
// value / v-model 绑定值 string / number —
value: [String, Number],
disabled:Boolean,
focused:Boolean,
readonly:Boolean
},
methods: {
// 聚焦
focus() {
this.getInput().focus();
},
// 失焦
blur() {
this.getInput().blur();
},
//双向绑定
handleInput(e)
{
this.$emit('input',e.target.value)
},
//聚焦事件
handleFocus(e){
this.$emit('focus', e);
},
//失焦事件
handleFBlur(e){
this.$emit('blur', e);
},
//获取ref
getInput()
{
return this.$refs.input
}
},
computed:{
// 监听原生值
nativeInputValue() {
return this.value === null || this.value === undefined ? '' : String(this.value);
},
//是否被禁用
inputdisabled(){
return this.disabled
},
}
}
</script>
标记
主要认识上标sub 和下标sup
图片
第一次了解到css的object-fit 属性,对图片进行处理剪切
在图片加载的时候自己定义了loading的样式
对插槽理解运用也更加熟练。
(侧边栏刷新没有记忆下来index值,导致没有到指定位置,本地储存可以实现,不知道有没有更好的方法)
<template>
<div class="fan-image">
<slot v-if="loading" name="placeholder">
<i class="el-icon-loading fan-loading-img"></i>
</slot>
<slot v-else-if="error" name='error'>
<div class="fan-image__error">加载失败</div>
</slot>
<img
v-else
class="fan-image__inner"
:src="src"
:alt="alt"
:style="{ 'object-fit': fit }">
</div>
</template>
<script>
export default {
name:'FanImage',
props:{
src:String,
alt:String,
fit:String,
},
//监听src变化
watch:{
src:{
handler(val){
this.loadImage(val);
},
immediate:true
}
},
data() {
return {
error:false,
loading:false
}
},
methods: {
// 加载图片
loadImage(val) {
// reset status
this.loading=true
setTimeout(()=>{
this.error = false;
const img = new Image();
img.onload = this.handleLoad.bind(this);
img.onerror = this.handleError.bind(this);
img.src = val;
},500)
},
// load 图片加载成功触发
handleLoad(e) {
this.loading=false
this.$emit('load', e);
},
// error 图片加载失败触发
handleError(e) {
this.loading=false
this.error = true;
this.$emit('error', e);
},
},
}
</script>
总结
看源码自己去写组件还是有很大的收获的,以前看vue文档会很迷糊,但现在配合组件开发会有很大的收获。
现在要结合vue文档和实例一起使用,才能高效性学习。
|