You've already forked guangan-mp
1.0.0
This commit is contained in:
317
uni_modules/uni-row/components/uni-col/uni-col.vue
Normal file
317
uni_modules/uni-row/components/uni-col/uni-col.vue
Normal file
@ -0,0 +1,317 @@
|
||||
<template>
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<view :class="['uni-col', sizeClass, pointClassList]" :style="{
|
||||
paddingLeft:`${Number(gutter)}rpx`,
|
||||
paddingRight:`${Number(gutter)}rpx`,
|
||||
}">
|
||||
<slot></slot>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<!-- 在nvue上,类名样式不生效,换为style -->
|
||||
<!-- 设置right正值失效,设置 left 负值 -->
|
||||
<view :class="['uni-col']" :style="{
|
||||
paddingLeft:`${Number(gutter)}rpx`,
|
||||
paddingRight:`${Number(gutter)}rpx`,
|
||||
width:`${nvueWidth}rpx`,
|
||||
position:'relative',
|
||||
marginLeft:`${marginLeft}rpx`,
|
||||
left:`${right === 0 ? left : -right}rpx`
|
||||
}">
|
||||
<slot></slot>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* Col 布局-列
|
||||
* @description 搭配uni-row使用,构建布局。
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=3958
|
||||
*
|
||||
* @property {span} type = Number 栅格占据的列数
|
||||
* 默认 24
|
||||
* @property {offset} type = Number 栅格左侧的间隔格数
|
||||
* @property {push} type = Number 栅格向右移动格数
|
||||
* @property {pull} type = Number 栅格向左移动格数
|
||||
* @property {xs} type = [Number, Object] <768px 响应式栅格数或者栅格属性对象
|
||||
* @description Number时表示在此屏幕宽度下,栅格占据的列数。Object时可配置多个描述{span: 4, offset: 4}
|
||||
* @property {sm} type = [Number, Object] ≥768px 响应式栅格数或者栅格属性对象
|
||||
* @description Number时表示在此屏幕宽度下,栅格占据的列数。Object时可配置多个描述{span: 4, offset: 4}
|
||||
* @property {md} type = [Number, Object] ≥992px 响应式栅格数或者栅格属性对象
|
||||
* @description Number时表示在此屏幕宽度下,栅格占据的列数。Object时可配置多个描述{span: 4, offset: 4}
|
||||
* @property {lg} type = [Number, Object] ≥1200px 响应式栅格数或者栅格属性对象
|
||||
* @description Number时表示在此屏幕宽度下,栅格占据的列数。Object时可配置多个描述{span: 4, offset: 4}
|
||||
* @property {xl} type = [Number, Object] ≥1920px 响应式栅格数或者栅格属性对象
|
||||
* @description Number时表示在此屏幕宽度下,栅格占据的列数。Object时可配置多个描述{span: 4, offset: 4}
|
||||
*/
|
||||
const ComponentClass = 'uni-col';
|
||||
|
||||
// -1 默认值,因为在微信小程序端只给Number会有默认值0
|
||||
export default {
|
||||
name: 'uniCol',
|
||||
// #ifdef MP-WEIXIN
|
||||
options: {
|
||||
virtualHost: true // 在微信小程序中将组件节点渲染为虚拟节点,更加接近Vue组件的表现
|
||||
},
|
||||
// #endif
|
||||
props: {
|
||||
span: {
|
||||
type: Number,
|
||||
default: 24
|
||||
},
|
||||
offset: {
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
pull: {
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
push: {
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
xs: [Number, Object],
|
||||
sm: [Number, Object],
|
||||
md: [Number, Object],
|
||||
lg: [Number, Object],
|
||||
xl: [Number, Object]
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
gutter: 0,
|
||||
sizeClass: '',
|
||||
parentWidth: 0,
|
||||
nvueWidth: 0,
|
||||
marginLeft: 0,
|
||||
right: 0,
|
||||
left: 0
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// 字节小程序中,在computed中读取$parent为undefined
|
||||
let parent = this.$parent;
|
||||
|
||||
while (parent && parent.$options.componentName !== 'uniRow') {
|
||||
parent = parent.$parent;
|
||||
}
|
||||
|
||||
this.updateGutter(parent.gutter)
|
||||
parent.$watch('gutter', (gutter) => {
|
||||
this.updateGutter(gutter)
|
||||
})
|
||||
|
||||
// #ifdef APP-NVUE
|
||||
this.updateNvueWidth(parent.width)
|
||||
parent.$watch('width', (width) => {
|
||||
this.updateNvueWidth(width)
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
computed: {
|
||||
sizeList() {
|
||||
let {
|
||||
span,
|
||||
offset,
|
||||
pull,
|
||||
push
|
||||
} = this;
|
||||
|
||||
return {
|
||||
span,
|
||||
offset,
|
||||
pull,
|
||||
push
|
||||
}
|
||||
},
|
||||
// #ifndef APP-NVUE
|
||||
pointClassList() {
|
||||
let classList = [];
|
||||
|
||||
['xs', 'sm', 'md', 'lg', 'xl'].forEach(point => {
|
||||
const props = this[point];
|
||||
if (typeof props === 'number') {
|
||||
classList.push(`${ComponentClass}-${point}-${props}`)
|
||||
} else if (typeof props === 'object' && props) {
|
||||
Object.keys(props).forEach(pointProp => {
|
||||
classList.push(
|
||||
pointProp === 'span' ?
|
||||
`${ComponentClass}-${point}-${props[pointProp]}` :
|
||||
`${ComponentClass}-${point}-${pointProp}-${props[pointProp]}`
|
||||
)
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
// 支付宝小程序使用 :class=[ ['a','b'] ],渲染错误
|
||||
return classList.join(' ');
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
methods: {
|
||||
updateGutter(parentGutter) {
|
||||
parentGutter = Number(parentGutter);
|
||||
if (!isNaN(parentGutter)) {
|
||||
this.gutter = parentGutter / 2
|
||||
}
|
||||
},
|
||||
// #ifdef APP-NVUE
|
||||
updateNvueWidth(width) {
|
||||
// 用于在nvue端,span,offset,pull,push的计算
|
||||
this.parentWidth = width;
|
||||
['span', 'offset', 'pull', 'push'].forEach(size => {
|
||||
const curSize = this[size];
|
||||
if ((curSize || curSize === 0) && curSize !== -1) {
|
||||
let RPX = 1 / 24 * curSize * width
|
||||
RPX = Number(RPX);
|
||||
switch (size) {
|
||||
case 'span':
|
||||
this.nvueWidth = RPX
|
||||
break;
|
||||
case 'offset':
|
||||
this.marginLeft = RPX
|
||||
break;
|
||||
case 'pull':
|
||||
this.right = RPX
|
||||
break;
|
||||
case 'push':
|
||||
this.left = RPX
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
watch: {
|
||||
sizeList: {
|
||||
immediate: true,
|
||||
handler(newVal) {
|
||||
// #ifndef APP-NVUE
|
||||
let classList = [];
|
||||
for (let size in newVal) {
|
||||
const curSize = newVal[size];
|
||||
if ((curSize || curSize === 0) && curSize !== -1) {
|
||||
classList.push(
|
||||
size === 'span' ?
|
||||
`${ComponentClass}-${curSize}` :
|
||||
`${ComponentClass}-${size}-${curSize}`
|
||||
)
|
||||
}
|
||||
}
|
||||
// 支付宝小程序使用 :class=[ ['a','b'] ],渲染错误
|
||||
this.sizeClass = classList.join(' ');
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
this.updateNvueWidth(this.parentWidth);
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='scss' scoped>
|
||||
/* breakpoints */
|
||||
$--sm: 768px !default;
|
||||
$--md: 992px !default;
|
||||
$--lg: 1200px !default;
|
||||
$--xl: 1920px !default;
|
||||
|
||||
$breakpoints: ('xs' : (max-width: $--sm - 1),
|
||||
'sm' : (min-width: $--sm),
|
||||
'md' : (min-width: $--md),
|
||||
'lg' : (min-width: $--lg),
|
||||
'xl' : (min-width: $--xl));
|
||||
|
||||
$layout-namespace: ".uni-";
|
||||
$col: $layout-namespace+"col";
|
||||
|
||||
@function getSize($size) {
|
||||
/* TODO 1/24 * $size * 100 * 1%; 使用计算后的值,为了解决 vue3 控制台报错 */
|
||||
@return 0.04166666666 * $size * 100 * 1%;
|
||||
}
|
||||
|
||||
@mixin res($key, $map:$breakpoints) {
|
||||
@if map-has-key($map, $key) {
|
||||
@media screen and #{inspect(map-get($map,$key))} {
|
||||
@content;
|
||||
}
|
||||
}
|
||||
|
||||
@else {
|
||||
@warn "Undeinfed point: `#{$key}`";
|
||||
}
|
||||
}
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
#{$col} {
|
||||
float: left;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#{$col}-0 {
|
||||
/* #ifdef APP-NVUE */
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin-top: 0;
|
||||
margin-right: 0;
|
||||
margin-bottom: 0;
|
||||
margin-left: 0;
|
||||
/* #endif */
|
||||
/* #ifndef APP-NVUE */
|
||||
display: none;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
@for $i from 0 through 24 {
|
||||
#{$col}-#{$i} {
|
||||
width: getSize($i);
|
||||
}
|
||||
|
||||
#{$col}-offset-#{$i} {
|
||||
margin-left: getSize($i);
|
||||
}
|
||||
|
||||
#{$col}-pull-#{$i} {
|
||||
position: relative;
|
||||
right: getSize($i);
|
||||
}
|
||||
|
||||
#{$col}-push-#{$i} {
|
||||
position: relative;
|
||||
left: getSize($i);
|
||||
}
|
||||
}
|
||||
|
||||
@each $point in map-keys($breakpoints) {
|
||||
@include res($point) {
|
||||
#{$col}-#{$point}-0 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@for $i from 0 through 24 {
|
||||
#{$col}-#{$point}-#{$i} {
|
||||
width: getSize($i);
|
||||
}
|
||||
|
||||
#{$col}-#{$point}-offset-#{$i} {
|
||||
margin-left: getSize($i);
|
||||
}
|
||||
|
||||
#{$col}-#{$point}-pull-#{$i} {
|
||||
position: relative;
|
||||
right: getSize($i);
|
||||
}
|
||||
|
||||
#{$col}-#{$point}-push-#{$i} {
|
||||
position: relative;
|
||||
left: getSize($i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
</style>
|
190
uni_modules/uni-row/components/uni-row/uni-row.vue
Normal file
190
uni_modules/uni-row/components/uni-row/uni-row.vue
Normal file
@ -0,0 +1,190 @@
|
||||
<template>
|
||||
<view :class="[ 'uni-row', typeClass , justifyClass, alignClass, ]" :style="{
|
||||
marginLeft:`${Number(marginValue)}rpx`,
|
||||
marginRight:`${Number(marginValue)}rpx`,
|
||||
}">
|
||||
<slot></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const ComponentClass = 'uni-row';
|
||||
const modifierSeparator = '--';
|
||||
/**
|
||||
* Row 布局-行
|
||||
* @description 流式栅格系统,随着屏幕或视口分为 24 份,可以迅速简便地创建布局。
|
||||
* @tutorial https://ext.dcloud.net.cn/plugin?id=3958
|
||||
*
|
||||
* @property {gutter} type = Number 栅格间隔
|
||||
* @property {justify} type = String flex 布局下的水平排列方式
|
||||
* 可选 start/end/center/space-around/space-between start
|
||||
* 默认值 start
|
||||
* @property {align} type = String flex 布局下的垂直排列方式
|
||||
* 可选 top/middle/bottom
|
||||
* 默认值 top
|
||||
* @property {width} type = String|Number nvue下需要自行配置宽度用于计算
|
||||
* 默认值 750
|
||||
*/
|
||||
|
||||
|
||||
export default {
|
||||
name: 'uniRow',
|
||||
componentName: 'uniRow',
|
||||
// #ifdef MP-WEIXIN
|
||||
options: {
|
||||
virtualHost: true // 在微信小程序中将组件节点渲染为虚拟节点,更加接近Vue组件的表现,可使用flex布局
|
||||
},
|
||||
// #endif
|
||||
props: {
|
||||
type: String,
|
||||
gutter: Number,
|
||||
justify: {
|
||||
type: String,
|
||||
default: 'start'
|
||||
},
|
||||
align: {
|
||||
type: String,
|
||||
default: 'top'
|
||||
},
|
||||
// nvue如果使用span等属性,需要配置宽度
|
||||
width: {
|
||||
type: [String, Number],
|
||||
default: 750
|
||||
}
|
||||
},
|
||||
created() {
|
||||
// #ifdef APP-NVUE
|
||||
this.type = 'flex';
|
||||
// #endif
|
||||
},
|
||||
computed: {
|
||||
marginValue() {
|
||||
// #ifndef APP-NVUE
|
||||
if (this.gutter) {
|
||||
return -(this.gutter / 2);
|
||||
}
|
||||
// #endif
|
||||
return 0;
|
||||
},
|
||||
typeClass() {
|
||||
return this.type === 'flex' ? `${ComponentClass + modifierSeparator}flex` : '';
|
||||
},
|
||||
justifyClass() {
|
||||
return this.justify !== 'start' ? `${ComponentClass + modifierSeparator}flex-justify-${this.justify}` : ''
|
||||
},
|
||||
alignClass() {
|
||||
return this.align !== 'top' ? `${ComponentClass + modifierSeparator}flex-align-${this.align}` : ''
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
$layout-namespace: ".uni-";
|
||||
$row:$layout-namespace+"row";
|
||||
$modifier-separator: "--";
|
||||
|
||||
@mixin utils-clearfix {
|
||||
$selector: &;
|
||||
|
||||
@at-root {
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
#{$selector}::before,
|
||||
#{$selector}::after {
|
||||
display: table;
|
||||
content: "";
|
||||
}
|
||||
|
||||
#{$selector}::after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@mixin utils-flex ($direction: row) {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: flex;
|
||||
/* #endif */
|
||||
flex-direction: $direction;
|
||||
}
|
||||
|
||||
@mixin set-flex($state) {
|
||||
@at-root &-#{$state} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
|
||||
#{$row} {
|
||||
position: relative;
|
||||
flex-direction: row;
|
||||
|
||||
/* #ifdef APP-NVUE */
|
||||
flex: 1;
|
||||
/* #endif */
|
||||
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
/* #endif */
|
||||
|
||||
// 非nvue使用float布局
|
||||
@include utils-clearfix;
|
||||
|
||||
// 在QQ、字节、百度小程序平台,编译后使用shadow dom,不可使用flex布局,使用float
|
||||
@at-root {
|
||||
|
||||
/* #ifndef MP-QQ || MP-TOUTIAO || MP-BAIDU */
|
||||
&#{$modifier-separator}flex {
|
||||
@include utils-flex;
|
||||
flex-wrap: wrap;
|
||||
flex: 1;
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
/* #ifndef APP-NVUE */
|
||||
display: none;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
@include set-flex(justify-center) {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@include set-flex(justify-end) {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
@include set-flex(justify-space-between) {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
@include set-flex(justify-space-around) {
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
@include set-flex(align-middle) {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@include set-flex(align-bottom) {
|
||||
align-items: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 字节、QQ配置后不生效
|
||||
// 此处用法无法使用scoped
|
||||
/* #ifdef MP-WEIXIN || MP-TOUTIAO || MP-QQ */
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
</style>
|
Reference in New Issue
Block a user