本來說弄個vue的專享,但是這個可能有些地方還沒你們了解的深入。
所以還是退而求其次來個技巧的分享吧。
只是簡單的說說一些比較好用的技巧,首先聊聊scss的一些指令吧
@each 指令的格式是 $var in <list>, $var可以是任何變量名,比如 $length 或者 $name,而 <list>是一連串的值,也就是值列表。
@each 將變量 $var 作用于值列表中的每一個項目,然后輸出結(jié)果,例如:
我的理解是有些類似于js中的字符串模板
//js字符串模板
const shareName = ' 技巧分享 '
console.log(`${shareName }`)
//scss中聲明的方式
.#{$var}-icon //類名 #{$var}
background-image: url('/images/#{$var}.png'); //樣式 字符串 #{$var}
text-align: $var !important; //樣式 $var
示例1
//注意 以下值列表的表現(xiàn)形式
@each $var in puma, sea-slug, egret, salamander {
.#{$var}-icon {
background-image: url('/images/#{$var}.png');
}
}
編譯為
.puma-icon {
background-image: url('/images/puma.png');
}
.sea-slug-icon {
background-image: url('/images/sea-slug.png');
}
.egret-icon {
background-image: url('/images/egret.png');
}
.salamander-icon {
background-image: url('/images/salamander.png');
}
示例2
// text align 文字位置
//注意 以下值列表的表現(xiàn)形式
@each $var in (left, center, right) {
.text-#{$var} {
text-align: $var !important;
}
}
//編譯為
.text-left {
text-align: left !important;
}
.text-center {
text-align: center !important;
}
.text-right {
text-align: right !important;
}
示例3
//colors 常用顏色
//值列表 鍵值對 map-get($colors,'bgc');
$colors: (
'bgc': #fbfbfb,
'bgh': #e7f3ff,
'blue':#2e85ff,
);
.text-bgc {
color: map-get($colors,'bgc');
}
//常見于組合使用
//設(shè)置之背景色和字體顏色
@each $colorKey, $color in $colors {
.text-#{$colorKey} {
color: $color;
}
.bg-#{$colorKey} {
background-color: $color;
}
}
//編譯為
.text-bgc {
color: #fbfbfb;
}
.bg-bgc {
background-color: #fbfbfb;
}
.text-bgh {
color: #e7f3ff;
}
.bg-bgh {
background-color: #e7f3ff;
}
.text-blue {
color: #2e85ff;
}
.bg-blue {
background-color: #2e85ff;
}
示例4
//比如還有以下的多重循環(huán) 在項目中可能很多地方都會使用到固定的margin padding值
//如以下三個值列表 在多重嵌套循環(huán)之后 就會編譯為我們所需要的形式
$spacing-types: (
m: margin,
p: padding
);
$spacing-base-size: 1px;
$spacing-sizes: (
10: 10,
25: 25,
55: 55
);
$spacing-directions: (
t: top,
r: right
);
// m-0, mx-0
@each $typeKey, $type in $spacing-types {
@each $directionKey, $direction in $spacing-directions {
@each $sizeKey, $size in $spacing-sizes {
.#{$typeKey}#{$directionKey}-#{$sizeKey} {
#{$type}-#{$direction}: $size * $spacing-base-size;
}
}
}
}
//編譯為
.mt-10 {
margin-top: 10px;
}
.mt-25 {
margin-top: 25px;
}
.mt-55 {
margin-top: 55px;
}
.mr-10 {
margin-right: 10px;
}
.mr-25 {
margin-right: 25px;
}
.mr-55 {
margin-right: 55px;
}
.pt-10 {
padding-top: 10px;
}
.pt-25 {
padding-top: 25px;
}
.pt-55 {
padding-top: 55px;
}
.pr-10 {
padding-right: 10px;
}
.pr-25 {
padding-right: 25px;
}
.pr-55 {
padding-right: 55px;
}
以上算是一個可以快速生成初始樣式便捷方式!
當(dāng)然除了@each 還有一些如 @mixin %box @function...
混合樣式
//Mixin 可以傳入?yún)?shù),直接復(fù)制屬性到每個選擇器里。 通過`@include`指令調(diào)用
//由于是復(fù)制 所以會有很多重復(fù)的樣式代碼
@mixin box($width: 100px, $height: 100px) {
width: $width;
height: $height;
box-shadow: 0px 0px 5px black;
margin: 10px;
}
.smallBox {
@include box(100px, 100px);
}
.bigBox {
@include box(300px, 300px);
}
//編譯后
.smallBox {
width: 100px;
height: 100px;
box-shadow: 0px 0px 5px black;
margin: 10px;
}
.bigBox {
width: 300px;
height: 300px;
box-shadow: 0px 0px 5px black;
margin: 10px;
}
占位符選擇器
//必須通過 `@extend`指令調(diào)用 %
//比 Mixin 要省很多代碼,它能將重復(fù)的代碼進(jìn)行提取
%box {
box-shadow: 0px 0px 5px black;
margin: 10px;
}
.bigBox {
@extend %box;
width: 300px;
height: 300px;
}
.smallBox {
@extend %box;
width: 100px;
height: 100px;
}
.bigBox {
@extend %box;
width: 300px;
height: 300px;
}
//編譯為
.bigBox, .smallBox {
box-shadow: 0px 0px 5px black;
margin: 10px;
}
.smallBox {
width: 100px;
height: 100px;
}
.bigBox {
width: 300px;
height: 300px;
}
函數(shù)指令
//以前做rem 布局時使用 現(xiàn)在px2rem-loader插件
//能將px單位轉(zhuǎn)化為rem
@function rem($a) {
@return $a / 100 + rem
};
.smallBox {
width: rem(50);
height: rem(50);
}
.bigBox {
width: rem(150);
height: rem(150);
}
//編譯為
.smallBox {
width: 0.5rem;
height: 0.5rem;
}
.bigBox {
width: 1.5rem;
height: 1.5rem;
}
使用熟練了可以省掉很多代碼的 三個類名就垂直居中了
<div class="d-flex jc-center ai-center">
<div class='smallBox '>
// doSomething 我是垂直居中的
</div>
</div>
// flex 配置
.d-flex {
display: flex;
}
$flex-jc: (
start: flex-start,
end: flex-end,
center: center,
between: space-between,
around: space-around,
);
$flex-ai: (
start: flex-start,
end: flex-end,
center: center,
stretch: stretch,
);
@each $key, $value in $flex-jc {
.jc-#{$key} {
justify-content: $value;
}
}
@each $key, $value in $flex-ai {
.ai-#{$key} {
align-items: $value;
}
}
好用的require.context
以下是一個自動全局注冊多個vue組件的腳本文件,避免了麻煩的一個個的找文件引入
import Vue from 'vue'
// 自動加載 common 目錄下的 .js 結(jié)尾的文件
const componentsContext = require.context('./common', true, /\.js$/)
componentsContext.keys().forEach(component => {
const componentConfig = componentsContext(component)
/**
* 兼容 import export 和 require module.export 兩種規(guī)范
*/
const ctrl = componentConfig.default || componentConfig
Vue.component(ctrl.name, ctrl)
})
require.context:它是webpack的api,通過執(zhí)行require.context函數(shù)會生成一個 context module(上下文模塊)。該context module包含一個map(映射)對象,會把requests翻譯成對應(yīng)的模塊id。
Request: 指在 require/import 語句中的表達(dá)式,如在 require("./common/" + name + ".js") 中的請求是 "./common/" + name + ".js"
//可以給這個函數(shù)傳入三個參數(shù)
//要搜索的目錄
//標(biāo)記表示是否還搜索其子目錄
//匹配文件的正則表達(dá)式。
require.context('./common', true, /\.js$/)
//源碼如下
var map = {
"./aa/index.js": "./src/components/common/aa/index.js",
"./bb/index.js": "./src/components/common/bb/index.js",
"./cc/index.js": "./src/components/common/cc/index.js"
};
function webpackContext(req) {
var id = webpackContextResolve(req);
return __webpack_require__(id);
}
function webpackContextResolve(req) {
if(!__webpack_require__.o(map, req)) {
var e = new Error("Cannot find module '" + req + "'");
e.code = 'MODULE_NOT_FOUND';
throw e;
}
return map[req];
}
webpackContext.keys = function webpackContextKeys() {
return Object.keys(map);
};
webpackContext.resolve = webpackContextResolve;
module.exports = webpackContext;
webpackContext.id = "./src/components/common sync recursive \\.js$";
require.context執(zhí)行后,返回一個方法webpackContext,這個方法又返回一個__webpack_require__,這個__webpack_require__就相當(dāng)于require或者import。同時webpackContext還有二個靜態(tài)方法keys與resolve,一個id屬性。
- id 是 context module 的模塊 id。
- keys 它返回一個數(shù)組,由所有可能被此 context module 處理的請求組成。
- resolve 它返回 request 被解析后得到的模塊 id。
-
webpackContext 返回的是一個模塊,這個模塊才是真正我們需要的。這個Module模塊和使用import導(dǎo)入的模塊是一樣的。
源碼

返回方法webpackContext,然后將key傳進(jìn)去,就能得到相應(yīng)的整個模塊。

在前端工程中,從一個文件夾引入很多模塊的情況的就會變得常見,此時建議使用這個api,它會遍歷指定的文件夾中的文件,自動導(dǎo)入,使得你不需要每次顯式的調(diào)用import導(dǎo)入模塊。
比如請求接口的時候,會分很多模塊,那么調(diào)用的時候需要一個個模塊的去找,此時就可以使用這個api,將請求接口的方法統(tǒng)一引入。除此之外還有很多地方都可以使用這個api,如svg、router、axios...


組件傳值
常用的就是
-
通過
prop向子組件傳數(shù)據(jù)
prop是你可以在組件上注冊的一些自定義特性。當(dāng)一個值傳遞給一個prop特性的時候,它就變成了那個組件實例 的一個屬性。
一個組件默認(rèn)可以擁有任意數(shù)量的prop,任何值都可以傳遞給任何prop。
我們可以在父組件中使用v-bind或簡寫:來動態(tài)傳遞prop。 -
通過事件向父級組件發(fā)送消息
Vue 實例提供了一個自定義事件的系統(tǒng)來解決這個問題。我們可以調(diào)用內(nèi)建的$emit方法并傳入事件的名字,來向父級組件觸發(fā)一個事件。 -
訪問元素 & 組件
ref被用來給元素或子組件注冊引用信息。引用信息將會注冊在父組件的$refs對象上。如果在普通的DOM元素上使用,引用指向的就是DOM元素;如果用在子組件上,引用就指向組件實例。
但是最近看了風(fēng)哥推薦的掘金小冊。看了看組件這一塊,平時也知道這種方式,但是一直沒有去細(xì)想。細(xì)想來就發(fā)現(xiàn)了組件調(diào)用的終極方式。
//父組件
<template>
<div id="app">
app
<aa></aa>
<bb></bb>
<cc></cc>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return {
name:'App1'
}
},
methods:{
getName(){
console.log(`這是${this.name}`)
}
}
}
</script>
//子組件
<template>
<div>
aa組件
</div>
</template>
<script>
export default {
name: 'aa',
data() {
return {
};
},
mounted() {
//如何找到父組件的name
console.log(this.$parent.name)
//如何找到父組件的getName方法
console.log(this.$parent.getName)
this.$parent.getName()
//如何找到兄弟組件
console.log(this.$parent.$children)
let children = this.$parent.$children.find(e => e.$options.name === 'cc')
console.log(children)
console.log(children.$options.name)
}
};
</script>
<style lang="scss" scoped>
</style>

它的適用場景:
- 由一個組件,向上找到最近的指定組件
- 由一個組件,向上找到所有的指定組件
- 由一個組件,向下找到最近的指定組件
- 由一個組件,向下找到所有的的指定組件
- 由一個組件,找到指定組件的兄弟組件
我感覺比依賴注入provide、inject更好用,結(jié)合起來就能大展手腳。
Map()數(shù)據(jù)結(jié)構(gòu)
JavaScript 的對象(Object),本質(zhì)上是鍵值對的集合(Hash 結(jié)構(gòu))。
區(qū)別
傳統(tǒng)Object鍵名只能是字符串形式
Map的鍵名可以是任意類型(包括對象)
特性
-
Map鍵名可以是任意類型 -
Map鍵名為對象類型時,與內(nèi)存地址綁定,如果內(nèi)存地址不同,就視為兩個鍵 - Map鍵名為簡單類型(數(shù)值,字符串,布爾值),只要兩個值嚴(yán)格相等(===),就認(rèn)為是一個鍵。
- NaN被視為同一個鍵,0和-0被視為同一個鍵
- 相同鍵多次賦值,后覆蓋前
實例的屬性和方法
- size屬性
返回Map成員總數(shù) - set(key, value)
設(shè)置鍵值對,返回Map本身,所以可以鏈?zhǔn)?/li> - get(key)
讀取key對應(yīng)的值,找不到返回undefined - has(key)
返回布爾值,表示是否存在 - delete(key)
刪除某鍵,返回布爾值,表示是否成功刪除 - clear()
清空所有成員,無返回值。
以及遍歷方法。
以下也簡單的講解一個例子說明其使用場景。
//如:需要根據(jù)用戶權(quán)限 展示對應(yīng)的操作按鈕。
//在以下場景中使用這種方式就會顯得非??旖莘奖?。
//鍵名不一樣 值是json格式的數(shù)據(jù)
let btns = new Map([ // 數(shù)據(jù)結(jié)構(gòu)map
// 已取消
['00', [{
text: '查看詳情',
key: 'details',
btnClass: 'ybBtn',
fun: (it) => this.gotoDetail(it.id)
}]],
// 待修改//已駁回
['01', [{
text: '修改資料',
key: 'modify',
btnClass: 'ybBtn',
fun: (it) => this.goModify(it)
}, {
text: '取消訂單',
key: 'cancel',
btnClass: 'ybBtn',
fun: (it) => this.goCancel(it)
}, {
text: '查看詳情',
key: 'details',
btnClass: 'ybBtn',
fun: (it) => this.gotoDetail(it.id)
}]],
// 待審核
['10', [{
text: '取消訂單',
key: 'cancel',
btnClass: 'ybBtn',
fun: (it) => this.goCancel(it)
}, {
text: '查看詳情',
key: 'details',
btnClass: 'ybBtn',
fun: (it) => this.gotoDetail(it.id)
}]],
// 待支付
['20', [{
text: '去支付',
key: 'pay',
btnClass: 'ybBtn',
fun: (it) => this.goPay(it)
}, {
text: '取消訂單',
key: 'cancel',
btnClass: 'ybBtn',
fun: (it) => this.goCancel(it)
}]]
])
console.log(btns)
console.table([...btns])

同樣是鍵值對的集合。但是鍵名不同的時候取值就會不那么便捷。如果是普通的map方法的話,要遍歷數(shù)組啊,找鍵名一致的啊,然后再去原數(shù)組中取值等,步驟繁多,顯得很冗長。但是使用Map來操作這種集合的時候。就能發(fā)現(xiàn)是真的好用。會顯得很優(yōu)雅。就一行。
//比如獲取`00`權(quán)限
let normal = btns.get('00')
console.log(normal)

愉快地時光總是短暫的
本期小技巧分享到此結(jié)束。
1、scss
2、require.context
3、組件傳值
4、Map()數(shù)據(jù)結(jié)構(gòu)
