如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
一、文字样式中阶
字体样式
代码格式:
font: 文字粗细 大小/行高 字体名称;
例子:font: bold 200px/400px "微软雅黑";
2.字体阴影
代码格式:
text-shadow:x y r color;
注:x是为负数则阴影向左,整数向右,同理y正数向上,负数向下,r代表阴影模糊程度,数值月大则越模糊,其单位都是px,color为文字颜色。
例子:text-shadow: 10px 10px 0px red;
提示:允许一段文字有多层阴影,多层之间用逗号隔开,每一层内,不同参数用空格隔开。
凹凸字体 阴影巧用
原理:通过背景颜色以及不同于背景颜色的阴影打造凹凸字体效果
例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>凹凸文字</title>
<style type="text/css">
body{
background: #ccc;
}
div{
color: #ccc;
text-align: center;
font: bold 200px/400px "微软雅黑";
/*text-shadow: 1px 1px 0px #fff;-1px -1px 0px #333;*/
text-shadow: 1px 1px 0px #333,-1px -1px 0px #fff;
}
</style>
</head>
<body>
<div >
凹凸文字
</div>
</body>
</html>
二、过渡属性
过渡属性的作用就是体现元素默认样式与最终样式变化的过程。
代码格式:transition:all 1s linear 0s;
注:
第一个参数的作用是设置元素的哪些属性过渡,all表示全部过渡,width代表属性宽度过渡,其他不过渡,其他属性也一样。
的哥属性设置过渡需要的时长,单位s不能省略。
第三个属性设置过渡延迟多少秒执行,单位s不能省略。
hover 设置鼠标移到某一元素时状态。
transition 这个属性既可以添加在元素默认状态,也可以添加在鼠标上移状态即添加在hover标签内,区别就是第二种做法在鼠标离开时候不会发生过渡变化。
例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>过渡属性</title>
<style type="text/css">
div{
width: 200px;
height: 200px;
background-color: green;
transition:all 1s linear 0s;
}
div:hover{
width: 600px;
background-color: yellow;
}
</style>
</head>
<body>
<div id="\">
</div>
</body>
</html>
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
话不多说,直接上问题图片
这里确认按钮是fixed布局 bottom:0 弹出键盘之后按钮被顶到了键盘上面
网上搜到的解决方案有两种,
一种是监听页面高度(我采用的这种)
一种是监听软键盘事件(ios和安卓实现方式不同,未采用)
下面是实现代码
data() {
return {
docmHeight: document.documentElement.clientHeight ||document.body.clientHeight,
showHeight: document.documentElement.clientHeight ||document.body.clientHeight,
hideshow:true //显示或者隐藏footer
}
},
watch: {
//监听显示高度
showHeight:function() {
if(this.docmHeight > this.showHeight){
//隐藏
this.hideshow=false
}else{
//显示
this.hideshow=true
}
}
},
mounted() {
//监听事件
window.onresize = ()=>{
return(()=>{
this.showHeight = document.documentElement.clientHeight || document.body.clientHeight;
})()
}
},
<div class="bottom" v-show="hideshow">
<div class="btn">
确认操作
</div>
</div>
我这里使用的是方法是:当键盘弹出时,将按钮隐藏。如果必须出现按钮的话,可以修改按钮回归到正常的流中。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
【Vue原理】Watch - 白话版
简述 响应式
监听的数据改变的时,watch 如何工作
设置 immediate 时,watch 如何工作
设置了 deep 时, watch 如何工作
举栗子
结论
没有设置 deep
设置了 deep
实际证明
专注 Vue 源码分享,为了方便大家理解,分为了白话版和 源码版,白话版可以轻松理解工作原理和设计思想,源码版可以更清楚内部操作和 Vue的美,喜欢我就关注我的公众号,公众号的文章,排版更好看
如果你觉得排版难看,请点击下面公众号链接
【Vue原理】Watch - 白话版
今天我们用白话文解读 watch 的工作原理,轻松快速理解 watch 内部工作原理。你说,你只懂怎么用的,却不懂他内部是怎么工作的,这样能有什么用?
近期有篇 《停止学习框架》很火,其实本意不是让我们不要学框架,而是让我们不要只停留在框架表面,我们要学会深入,以一敌十,让我们也要学会框架的抽象能力
watch 想必大家用得应该也挺多的,用得也很顺,如果你顺便花一点点时间了解一下内部的工作原理,相信肯定会对你的工作有事半功倍的效果
watch 的工作原理其实挺简单的,如果你有看过我之前讲解其他选项的文章,你可以一下子就明白 watch 是如何工作的,所以这边文章我也✍得很快
根据 watch 的 api,我们需要了解三个地方
1、监听的数据改变的时,watch 如何工作
2、设置 immediate 时,watch 如何工作
3、设置了 deep 时,watch 如何工作
简述 响应式
Vue 会把数据设置响应式,既是设置他的 get 和 set
当 数据被读取,get 被触发,然后收集到读取他的东西,保存到依赖收集器
当 数据被改变,set 被触发,然后通知曾经读取他的东西进行更新
如果你不了解,可以查看下 以前的文章
【Vue原理】响应式原理 - 白话版
监听的数据改变的时,watch 如何工作
watch 在一开始初始化的时候,会 读取 一遍 监听的数据的值,于是,此时 那个数据就收集到 watch 的 watcher 了
然后 你给 watch 设置的 handler ,watch 会放入 watcher 的更新函数中
当 数据改变时,通知 watch 的 watcher 进行更新,于是 你设置的 handler 就被调用了
设置 immediate 时,watch 如何工作
当你设置了 immediate 时,就不需要在 数据改变的时候 才会触发。
而是在 初始化 watch 时,在读取了 监听的数据的值 之后,便立即调用一遍你设置的监听回调,然后传入刚读取的值
设置了 deep 时, watch 如何工作
我们都知道 watch 有一个 deep 选项,是用来深度监听的。什么是深度监听呢?就是当你监听的属性的值是一个对象的时候,如果你没有设置深度监听,当对象内部变化时,你监听的回调是不会被触发的
在说明这个之前,请大家先了解一下
当你使用 Object.defineProperty 给 【值是对象的属性】 设置 set 和 get 的时候
1如果你直接改变或读取这个属性 ( 直接赋值 ),可以触发这个属性的设置的 set 和 get
2但是你改变或读取它内部的属性,get 和 set 不会被触发的
举栗子
var inner = { first:1111 }
var test={ name:inner }
Object.defineProperty(test,"name",{
get(){
console.log("name get被触发")
return inner
},
set(){
console.log("name set被触发")
}
})
// 访问 test.name 第一次,触发 name 的 get
Object.defineProperty(test.name,"first",{
get(){
return console.log("first get被触发")
},
set(){
console.log("first set被触发")
}
})
// 访问 test.name 第二次,触发 name 的 get
var a = test.name
// 独立访问 first 第一次
var b= a.first
// 独立访问 first 第二次
b= a.first
// 独立改变 first
a.first = 5
能看到除了有两次需要访问到 name,必不可少会触发到 name 的 get
之后,当我们独立访问 name 内部的 first 的时,只会触发 first 的 get 函数,而 name 设置的 get 并不会被触发
结论
看上面的例子后,所以当你的 data 属性值是对象,比如下面的 info
data(){
return {
info:{ name:1 }
}
}
此时,Vue在设置响应式数据的时候, 遇到值是对象的,会递归遍历,把对象内所有的属性都设置为响应式,就是每个属性都设置 get 和 set,于是每个属性都有自己的一个依赖收集器
首先,再次说明,watch初始化的时候,会先读取一遍监听数据的值
没有设置 deep
1、因为读取了监听的 data 的属性,watch 的 watcher 被收集在 这个属性的 收集器中
设置了 deep
1、因为读取了监听的data 的属性,watch 的 watcher 被收集在 这个属性的 收集器中
2、在读取 data 属性的时候,发现设置了 deep 而且值是一个对象,会递归遍历这个值,把内部所有属性逐个读取一遍,于是 属性和 它的对象值内每一个属性 都会收集到 watch 的 watcher
于是,无论对象嵌套多深的属性,只要改变了,会通知 相应的 watch 的 watcher 去更新,于是 你设置的 watch 回调就被触发了
实际证明
证明 watch 的 watcher 深度监听时是否被内部每个属性都收集
我在 Vue 内部给 watch 的 watcher 加了一个 属性,标识他是 watch 的 watcher,并且去掉了多余的属性,为了截图短一点
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
1.无序列表
无序列表是网页中最常用的列表,之所以称为“无序列表”,是因为其各个列表项之间为并列关系,没有顺序级别之分,列如:
<ul>
<li>列表1</li>
<li>列表2</li>
<li>列表3</li>
</ul>
2.有序列表
有序列表即为有顺序的列表,其各个列表项会按照一定的顺序排列,列如:
<ol>
<li>列表1</li>
<li>列表2</li>
<li>列表3</li>
</ol>
注:列表可以嵌套。
3.超链接标记< a>
1.超链接
一个网站通常由多个页面构成,进入网站时首先看到的是其首页,如果想从首页跳转到其子页面,就需要在首页相应的位置添加超链接。其基本语法格式为:
<a href="跳转目标" target=“目标窗口的弹出方式”>文本或者图像</a>
1
其中,target有两种取值方式:
–blank (在新窗口中打开)-self(默认在本窗口打开)
2.伪类
超链接标记< a >的伪类 含义
a:link{ CSS样式规则; } 未访问时超链接的状态
a:visited{ CSS样式规则;} 访问之后超链接的状态
a:hover{ CSS样式规则;} 鼠标经过,悬停时超链接的状态
a:active{ CSS样式规则;} 鼠标单击不动时超链接的状态
---------------------
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
HTML 中的div定义:
可定义文档中的分区或节(division/section)。
标签可以把文档分割为独立的、不同的部分。它可以用作严格的组织工具,并且不使用任何格式与其关联。
如果用 id 或 class 来标记 div,那么该标签的作用会变得更加有效。
用法
div是一个块级元素。这意味着它的内容自动地开始一个新行。实际上,换行是
固有的唯一格式表现。可以通过 div的 class 或 id 应用额外的样式。
不必为每一个 div都加上类或 id,虽然这样做也有一定的好处。
可以对同一个 div 元素应用 class 或 id 属性,但是更常见的情况是只应用其中一种。这两者的主要差异是,class 用于元素组(类似的元素,或者可以理解为某一类元素),而 id 用于标识单独的唯一的元素。
实例
<div id = " text"><div> <div class = " text1"><div> <div class = " text1"><div>
//div 中可以设置id属性,通过引用id属性来为div设置一些样式
//在style标签中,可以对你写的代码进行样式的设计,样式设计可以通过以下几种方法来写
1.通过引用id来设置样式,在id名称前加上# 格式: #id名称{ }
#text{ }
2.通过class来设置样式,class后面的名字可以是一样的,而id取名唯一,因此在需要设置同类型的样式时可以使用class来设置 格式: .class名称{ }
.text1{ }
3.通过标签名称来设置样式 格式: div{ }
div{ }
样式:
1.width :50px; // 宽度
2.height :50px;//高度
3.border : 1px solid red; //边框,border可以设置三个属性,分别是边框宽度,边框样式(实线,虚线等),边框颜色
4.margin:属性定义及使用说明
margin简写属性在一个声明中设置所有外边距属性。该属性可以有1到4个值。
实例:
margin:10px 5px 15px 20px;
上边距是 10px
右边距是 5px
下边距是 15px
左边距是 20px
margin:10px 5px 15px;
上边距是 10px
右边距和左边距是 5px
下边距是 15px
margin:10px 5px;
上边距和下边距是 10px
右边距和左边距是 5px
margin:10px;
所有四个边距都是 10px
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
1 状态共享
随着组件的细化,就会遇到多组件状态共享的情况,Vuex当然可以解决这类问题,不过就像Vuex官方文档所说的,如果应用不够大,为避免代码繁琐冗余,最好不要使用它,今天我们介绍的是vue.js 2.6新增加的Observable API ,通过使用这个api我们可以应对一些简单的跨组件数据状态共享的情况。
如下这个例子,我们将在组件外创建一个store,然后在App.vue组件里面使用store.js提供的store和mutation方法,同理其它组件也可以这样使用,从而实现多个组件共享数据状态。
首先创建一个store.js,包含一个store和一个mutations,分别用来指向数据和处理方法。
import Vue from "vue";
export const store = Vue.observable({ count: 0 });
export const mutations = {
setCount(count) {
store.count = count;
}
};
复制代码
然后在App.vue里面引入这个store.js,在组件里面使用引入的数据和方法
<template>
<div id="app">
<img width="25%" src="./assets/logo.png">
<p>count:{{count}}</p>
<button @click="setCount(count+1)">+1</button>
<button @click="setCount(count-1)">-1</button>
</div>
</template>
<script>
import { store, mutations } from "./store";
export default {
name: "App",
computed: {
count() {
return store.count;
}
},
methods: {
setCount: mutations.setCount
}
};
</script>
<style>
复制代码
你可以点击在线DEMO查看最终效果
2 长列表性能优化
我们应该都知道vue会通过object.defineProperty对数据进行劫持,来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,不会有任何改变,我们就不需要vue来劫持我们的数据,在大量数据展示的情况下,这能够很明显的减少组件初始化的时间,那如何禁止vue劫持我们的数据呢?可以通过object.freeze方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了。
export default {
data: () => ({
users: {}
}),
async created() {
const users = await axios.get("/api/users");
this.users = Object.freeze(users);
}
};
复制代码
另外需要说明的是,这里只是冻结了users的值,引用不会被冻结,当我们需要reactive数据的时候,我们可以重新给users赋值。
export default {
data: () => ({
users: []
}),
async created() {
const users = await axios.get("/api/users");
this.users = Object.freeze(users);
},
methods:{
// 改变值不会触发视图响应
this.users[0] = newValue
// 改变引用依然会触发视图响应
this.users = newArray
}
};
复制代码
3 去除多余的样式
随着项目越来越大,书写的不注意,不自然的就会产生一些多余的css,小项目还好,一旦项目大了以后,多余的css会越来越多,导致包越来越大,从而影响项目运行性能,所以有必要在正式环境去除掉这些多余的css,这里推荐一个库purgecss,支持CLI、JavascriptApi、Webpack等多种方式使用,通过这个库,我们可以很容易的去除掉多余的css。
我做了一个测试,在线DEMO
<h1>Hello Vanilla!</h1>
<div>
We use Parcel to bundle this sandbox, you can find more info about Parcel
<a href="https://parceljs.org" target="_blank" rel="noopener noreferrer">here</a>.
</div>
复制代码
body {
font-family: sans-serif;
}
a {
color: red;
}
ul {
li {
list-style: none;
}
} import Purgecss from "purgecss";
const purgecss = new Purgecss({
content: ["**/*.html"],
css: ["**/*.css"]
});
const purgecssResult = purgecss.purge();
终产生的purgecssResult结果如下,可以看到多余的a和ul标签的样式都没了
4 作用域插槽
利用好作用域插槽可以做一些很有意思的事情,比如定义一个基础布局组件A,只负责布局,不管数据逻辑,然后另外定义一个组件B负责数据处理,布局组件A需要数据的时候就去B里面去取。假设,某一天我们的布局变了,我们只需要去修改组件A就行,而不用去修改组件B,从而就能充分复用组件B的数据处理逻辑,关于这块我之前写过一篇实际案例,可以点击这里查看。
这里涉及到的一个最重要的点就是父组件要去获取子组件里面的数据,之前是利用slot-scope,自vue 2.6.0起,提供了更好的支持 slot和 slot-scope 特性的 API 替代方案。
比如,我们定一个名为current-user的组件:
<span>
<slot>{{ user.lastName }}</slot>
</span>
复制代码
父组件引用current-user的组件,但想用名替代姓(老外名字第一个单词是名,后一个单词是姓):
<current-user>
{{ user.firstName }}
</current-user>
复制代码
这种方式不会生效,因为user对象是子组件的数据,在父组件里面我们获取不到,这个时候我们就可以通过v-slot 来实现。
首先在子组件里面,将user作为一个<slot>元素的特性绑定上去:
<span>
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>
复制代码
之后,我们就可以在父组件引用的时候,给v-slot带一个值来定义我们提供的插槽 prop 的名字:
<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>
复制代码
这种方式还有缩写语法,可以查看独占默认插槽的缩写语法,最终我们引用的方式如下:
<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
</current-user>
复制代码
相比之前slot-scope代码更清晰,更好理解。
5 属性事件传递
写过高阶组件的童鞋可能都会碰到过将加工过的属性向下传递的情况,如果碰到属性较多时,需要一个个去传递,非常不友好并且费时,有没有一次性传递的呢(比如react里面的{...this.props})?答案就是v-bind和v-on。
举个例子,假如有一个基础组件BaseList,只有基础的列表展示功能,现在我们想在这基础上增加排序功能,这个时候我们就可以创建一个高阶组件SortList。
<!-- SortList -->
<template>
<BaseList v-bind="$props" v-on="$listeners"> <!-- ... --> </BaseList>
</template>
<script>
import BaseList from "./BaseList";
// 包含了基础的属性定义
import BaseListMixin from "./BaseListMixin";
// 封装了排序的逻辑
import sort from "./sort.js";
export default {
props: BaseListMixin.props,
components: {
BaseList
}
};
</script>
复制代码
可以看到传递属性和事件的方便性,而不用一个个去传递
6 函数式组件
函数式组件,即无状态,无法实例化,内部没有任何生命周期处理方法,非常轻量,因而渲染性能高,特别适合用来只依赖外部数据传递而变化的组件。
写法如下:
在template标签里面标明functional
只接受props值
不需要script标签
<!-- App.vue -->
<template>
<div id="app">
<List
:items="['Wonderwoman', 'Ironman']"
:item-click="item => (clicked = item)"
/>
<p>Clicked hero: {{ clicked }}</p>
</div>
</template>
<script>
import List from "./List";
export default {
name: "App",
data: () => ({ clicked: "" }),
components: { List }
};
</script>
复制代码
<!-- List.vue 函数式组件 -->
<template functional>
<div>
<p v-for="item in props.items" @click="props.itemClick(item);">
{{ item }}
</p>
</div>
</template>
复制代码
7 监听组件的生命周期
比如有父组件Parent和子组件Child,如果父组件监听到子组件挂载mounted就做一些逻辑处理,常规的写法可能如下:
// Parent.vue
<Child @mounted="doSomething"/>
// Child.vue
mounted() {
this.$emit("mounted");
}
复制代码
这里提供一种特别简单的方式,子组件不需要任何处理,只需要在父组件引用的时候通过@hook来监听即可,代码重写如下:
<Child @hook:mounted="doSomething"/>
复制代码
当然这里不仅仅是可以监听mounted,其它的生命周期事件,例如:created,updated等都可以,是不是特别方便~
参考链接:
vueTips
vuePost
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例</title>
<script src="../static/vue.min.js"></script>
</head>
<body>
<div id="vue_data">
<h1>title : {{title}}</h1>
<h1>url : {{url}}</h1>
<h1>{{info()}}</h1>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#vue_data',
data: {
title: "Vue.js",
url: "https://cn.vuejs.org"
},
methods: {
info: function() {
return this.title + " - 坚持学习!";
}
}
})
</script>
</body>
</html>
1、每个Vue应用都需要实例化Vue来实现
var vm = new Vue({
//*******
})
2、el参数
在上面实例中的id为vue_data,在div元素中:
<div id="vue_data"></div>
意味着所有的改动均在这个id为vau_data的div中,外部不受影响。
3、定义数据对象
data用于定义属性,在上述实例中有2个属性,分别为:title、url。
methods用于定义函数,可以通过return来返回函数值。
{{ }}用于输出对象属性和函数返回值。
当一个Vue实例创建时,Vue的响应系统加入了data对象中能找到的所有属性。当这些属性的值发生改变时,html视图也会产生相应的变化。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue 测试实例</title>
<script src="../static/vue.min.js"></script>
</head>
<body>
<div id="vue_data">
<h1>title : {{title}}</h1>
<h1>url : {{url}}</h1>
</div>
<script type="text/javascript">
//数据对象
var data = {title: "Vue.js",url: "https://cn.vuejs.org"}
var vm = new Vue({
el: '#vue_data',
data: data
})
//设置属性会影响到原始数据
vm.title = "spring";
document.write(data.title + "<br>");
//同样
data.url = "https://spring.io";
document.write(vm.url);
</script>
</body>
</html>
Vue还提供了实例属性与方法,以前缀$与用户定义的属性区分开来。
document.write(vm.$data === data) // true
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
使用新版本的弹性伸缩布局
display使用弹性伸缩盒
direction容器盒内元素的排列顺序
flex-wrap设置无法容纳时,自动换行
justify-content 伸缩项目的排列方式
align-items 处理额外空间
align-self 单独处理一个伸缩项目的额外空间
flex 控制伸缩容器的比例分配
order 设置伸缩项目出现的位置
dislpay
值:
flex 将容器盒作为块级弹性伸缩盒显示。
inline-flex:将容器盒作为内联级弹性伸缩盒显示。
实际现实中 这两个值没区别。
direction
容器盒内元素的排列顺序
值:
row:从左到右排列
row-reverse:从右到左排列
column:从上倒下排列
column-reverse从下到上排列
flex-wrap
设置无法容纳时,自动换行
值:
nowrap:不换行
wrap:自动换行
wrap-reverse:自动换行,方向和wrap相反
下图为正常排序
使用wrap-reverse后缩小浏览器时:
justify-content
伸缩项目的排列方式
值:
flex-start:伸缩项目以起始点靠齐
flex-end:伸缩项目以结尾靠齐
center:以中心点靠齐
space-between:伸缩项目平均分布
space-around:同上但两段保留一般的空间
实例:使用space-around的排列效果
align-items
处理额外空间
值:
flex-start:以顶部为基准,清理底部的额外空间
flex-end:以底部为基准,清理顶部的额外空间
center:以中间为基准,清理上下部分的额外空间
baseline:以基线为基准,清理额外的空间
stretch:伸缩项目填充整个容器,默认值
align-self
处理额外空间
值:与align-items的值一样,需要用nth-child()设置某一个需要处理的伸缩项目
flex
设置伸缩项目分配比例
p:nth-child(1)
{
flex: 1;
}
p:nth-child(2)
{
flex: 2;
}
p:nth-child(3)
{
flex: 2;
}
p:nth-child(4)
{
flex: 1;
}
order
设置伸缩项目出现的位置
p:nth-child(1)
{
order:2;
}
p:nth-child(2)
{
order:3;
}
p:nth-child(3)
{
order:4;
}
p:nth-child(4)
{
order:1;
}
---------------------
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
做了一个项目,有充值功能,充值方式为 微信和支付宝,效果如下:
代码:
<template>
<el-card class="box-card">
<ul class="msg-box">
<li>
<h4>我要充值</h4>
</li>
<li>
<h4 style="margin-bottom: 15px;">充值金额</h4>
<el-radio-group v-model="amountVal" @change="amountChange">
<el-radio border :label="''+ 100">充值100</el-radio>
<el-radio border :label="''+ 500">充值500</el-radio>
<el-radio border :label="''+ 1000">充值1000</el-radio>
<el-radio border :label="''+ 2000">充值2000</el-radio>
<el-radio border :label="''+ 5000">充值5000</el-radio>
<el-radio border :label="''">自定义</el-radio>
</el-radio-group>
</li>
<li>
<h4 style="margin-bottom: 15px;">充值方式</h4>
<el-radio-group v-model="rechargeParams.paymentType" @change="paymentTypeChange">
<el-radio border :label="''+ 0">微信</el-radio>
<el-radio border :label="''+ 1">支付宝</el-radio>
</el-radio-group>
</li>
<li>
<h4 style="margin-bottom: 15px;">充值金额</h4>
<el-input :disabled="disabled" clearable v-model="rechargeParams.totalAmt" placeholder="请输入金额" style="width: 150px;"></el-input>
</li>
</ul>
<div style="text-align: center; margin-top: 30px;">
<el-button type="primary" @click="surePay">确认支付</el-button>
</div>
</el-card>
</template>
<script>
export default {
data() {
return {
amountVal: '',
disabled: false,
//充值参数
rechargeParams: {
"totalAmt": '', //金额
"paymentType": "0", //支付方式[0:微信,1:支付宝,2:余额,3:活动]
"transType": "0" //交易类型[0:充值,1:消费]
}
}
},
methods: {
//充值金额
amountChange(val) {
this.rechargeParams.totalAmt = val;
if (val == '') {
this.disabled = false
} else {
this.disabled = true
}
},
//支付方式
paymentTypeChange(val) {
this.rechargeParams.paymentType = val
},
//确认支付
async surePay() {
if (this.rechargeParams.totalAmt == '') {
this.$message.warning('请输入金额');
return;
}
const res = await this.$http.post('orderInfo/createOrderInfo', this.rechargeParams)
const {
code,
msg,
result
} = res.data
if (code === '200') {
//支付方式跳转
if (this.rechargeParams.paymentType == '0') {
this.$message.success('微信支付');
this.wechatPay(result);
} else if (this.rechargeParams.paymentType == '1') {
this.$message.success('支付宝支付')
const payDiv = document.getElementById('payDiv');
if (payDiv) {
document.body.removeChild(payDiv);
}
const div = document.createElement('div');
div.id = 'payDiv';
div.innerHTML = result;
document.body.appendChild(div);
document.getElementById('payDiv').getElementsByTagName('form')[0].submit();
} else if (this.rechargeParams.paymentType == '2') {
this.$message.success('余额支付成功');
this.$router.push({
name: 'order'
})
} else {
this.$message.success('活动支付')
}
} else if (code === 401) {
this.$message.error(msg)
this.$router.push({
name: 'login'
})
} else {
this.$message.error(msg)
}
},
//微信支付
wechatPay(result) {
if (result) {
const orderParams = JSON.parse(result);
sessionStorage.qrurl = orderParams.qrurl;
sessionStorage.amt = orderParams.amt;
sessionStorage.returnUrl = orderParams.returnUrl;
sessionStorage.order_id = orderParams.order_id;
this.$router.push({
name: 'wechatPay'
})
}
}
}
}
</script>
<style scoped>
/* 信息列表样式 */
.msg-box > li {
list-style: none;
border-bottom: 1px solid #c5c5c5;
padding: 20px 10px;
}
</style>
支付宝方式:后台会返回来一个form,然后提交form自动跳转到支付宝支付页面。
微信方式:需要自己根据后台返回的url生成二维码页面,如图所示:
代码:
<template>
<div class="payBox">
<div class="img-logo">
<img src="http://img.huoxingbeidiao.com/public/WePayLogo.png" alt="">
</div>
<div class="info-box">
<div style="padding-bottom: 20px;">
<qrcode-vue :value="qrurl" :size="200" level="H"></qrcode-vue>
</div>
<img src="http://img.huoxingbeidiao.com/public/WePayInfo.png" alt="">
<p class="price">¥ {{amt}}</p>
</div>
</div>
</template>
<script>
import QrcodeVue from 'qrcode.vue'
export default {
data() {
return {
amt: 0,
qrurl: '',
timer: null
}
},
components: {
QrcodeVue
},
methods: {
getOrderInfo() {
if (sessionStorage.qrurl && sessionStorage.amt) {
this.qrurl = sessionStorage.qrurl;
this.amt = sessionStorage.amt;
}
},
startLoop() {
this.timer = setInterval(() => {
this.isPaySuccess()
}, 3000)
},
async isPaySuccess() {
const orderId = sessionStorage.order_id;
const res = await this.$http.get('orderInfo/queryOrder?orderId=' + orderId)
const {
code,
msg,
resultList
} = res.data
if (code === '200') {
clearInterval(this.timer);
this.timer = null;
sessionStorage.removeItem('qrurl');
sessionStorage.removeItem('amt');
sessionStorage.removeItem('order_id');
sessionStorage.removeItem('returnUrl');
setTimeout(() => {
this.$router.push({
name: 'order'
})
}, 3000)
} else if (code === 401) {
clearInterval(this.timer);
this.timer = null;
sessionStorage.removeItem('qrurl');
sessionStorage.removeItem('amt');
sessionStorage.removeItem('order_id');
sessionStorage.removeItem('returnUrl');
this.$message.error(msg)
this.$router.push({
name: 'login'
})
} else {
}
}
},
created() {
this.getOrderInfo()
this.startLoop()
},
beforeDestroy() {
clearInterval(this.timer)
this.timer = null
}
}
</script>
<style scoped>
.payBox {
width: 1000px;
margin: 0 auto;
}
.payBox .img-logo {
padding: 20px 0;
text-align: center;
}
.payBox .img-logo img {
width: 180px;
}
.info-box {
padding: 60px 0;
border-top: 3px solid #F43B66;
-webkit-box-shadow: 0 0 32px 0 rgba(0, 0, 0, .18);
box-shadow: 0 0 32px 0 rgba(0, 0, 0, .18);
text-align: center;
}
.info-box .price {
color: #F43B66;
font-size: 40px;
padding-top: 20px;
padding-bottom: 20px;
border-bottom: 1px solid #f1f1f1;
}
</style>
需要安装qrcode.vue
npm install --save qrcode.vue 或 yarn add qrcode.vue
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
ID选择器>类选择器>标签选择器
行内样式>内部样式>外部样式
*结构伪类选择器 一旦设置 不管在行内还是在后面重新设置,都没办法改变
*结构伪类选择器设置奇偶行以及从第三行开始变色如何实现
nth-cild(2N+3)表示从第三行开始的奇数行
同理 nth-child(2N+4)表示从第四行开始的偶数行
nth-cild(2N+5)表示从第五行开始的奇数行
*设置前三个:
p:nth-child(-n+3){
background-color: #b3d4fc;
}
*使用E F:nth-child(n)和E F:nth-of-type(n)的 关键点
E F:nth-child(n)在父级里从一个元素开始查找,不分类型
E F:nth-of-type(n)在父级里先看类型,再看位置
注意
child 跟子选择器没有关系,可以是子选择,也可以是后代选择 由层次选择器 (如table tr)来控制
1.层次选择器
table td 后代选择器 td包含在table里
div>p子选择器 p是div的子元素
p1+p p1后面一个兄弟p变化 是对p进行处理 p1不变 而且只是下面相邻的变化 上面相邻不变化
p1~p p1后面所有兄弟p变化 p1不变
2.结构伪类选择器
P:first-child 作为父元素的第一个子元素得元素 p
P:last-child 作为父元素的最后一个子元素得元素 p
P a :nth-child(n) p中第n个a元素 (even)(odd)
p:first-of-type 必须是p元素 不是子元素也行
p a:nth-of-type(n)
必须是a元素 不是a的子元素也行
3.属性选择器
a[id] a标签中含有id的
a[id=111] a标签中的id=111的
a[href*=http] a标签中包含href属性 且都包含http
a[href&=png] a标签中包含href属性 且最后以png结尾
a[href^=http://] a标签中包含href属性且以http://开头
1.层次选择器
*相邻兄弟选择器,只对后面的兄弟有作用,对前面的兄弟没效果。
*相邻兄弟选择器,E+F E不会产生效果效果
2.结构伪类选择器
使用E F:nth-child(n)和E F:nth-of-type(n)的 关键点
E F:nth-child(n)在父级里从一个元素开始查找,不分类型
E F:nth-of-type(n)在父级里先看类型,再看位置
注意
child 跟子选择器没有关系,可以是子选择,也可以是后代选择 由层次选择器 (如table tr)来控制
设置前三个:
p:nth-child(-n+3){
background-color: #b3d4fc;
}
3.属性选择器
举例:
a[href=^http]{backgroud-color:red}
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
蓝蓝设计的小编 http://www.lanlanwork.com