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文档和实例一起使用,才能高效性学习。