配置路徑@(一般情況下搭建vue-cli,項目已經配置好了@路徑。若自己需要改動可按照一下方法)
vue-cli 2.x 版本創建項目時,我們可以在 build 文件夾下找到 webpack.base.conf.js 文件,在里面修改 resolve.alias 即可
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
vue-cli 3.0 創建項目時,目錄結構精簡化,找不到 build 和 config 文件夾,那么該如何修改路徑別名呢?
由於vue-cli 3.0 版本所有的配置項都放在了 vue.config.js 文件中,所以在里面進行配置就好了,代碼如下:
const path = require('path');
function resolve (dir) {
return path.join(__dirname, dir)
}
// 項目的主要配置文件
module.exports = {
// webpack 配置進行更細粒度的修改 https://cli.vuejs.org/zh/config/#chainwebpack
chainWebpack: (config)=>{
//修改文件引入自定義路徑
config.resolve.alias
.set('@', resolve('src'))
.set('style', resolve('src/assets/style'))
}
}
配置好想用的路徑別名后,重新啟動項目,再引入文件時,使用別名即可
import Demo from '@/demo/demoweb'
使用iconfont
1、在assets文件夾下新建iconfont文件夾
2、從iconfont下載字體圖標包,下載下來之后,將文件中的這6個文件放入iconfont中(見下圖)
3、在main.js中引入:import './assets/iconfont/iconfont.css'
(若有報錯,安裝css-loader包)
如何實現橫向滾動(兼容safari,微信,瀏覽器)
實現橫向滾動需要以下幾點:
1、設置width:2000px這種大的寬度
2、父級盒子要overflow-y:hidden;overflow-x:auto來防止頁面寬度溢出,以及實現左右滾動效果
3、::-webkit-scrollbar { display: none;}隱藏橫向滾動條(此方法在ios和微信端無效),所以第四步實現兼容
4、滾動條所存在的盒子為g,g之外再設置一個父盒子s並給定高度和overflow:hidden。通過s來遮蓋g的滾動條即可實現隱藏滾動條。
示例:
<template>
<div class="university">
<div class="container">
<div class="scrollHidden"> <!--此盒子設置:height,overflow:hidden-->
<div class="body"> <!--此盒子設置:滾動條overflow-y:hidden,overflow-x:auto,滾動條display:none,padding-bottom-->
<ul class="body_content"> <!--此盒子設置 :2000px寬度-->
<li v-for="(item,index) in universityList" :key="index" class="every_content"> <!--此盒子設置: 浮動-->
<div class="content_img"><img :src="item.pimage" /></div>
<div class="content_name">{{item.pname}}</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</template>
<script></script>
<style scoped lang="less">
.university{
.container{
.scrollHidden{
height:152px; //7、設置固定高度(以子盒子為准)
overflow:hidden; //8、超出部分影隱藏
.body{
overflow-y: hidden; //2、父級盒子:豎向超出部分隱藏
overflow-x: auto; //3、父級盒子:控制橫向可滾動,配合overflow-y:hidden共同控制內容不溢出當前屏幕
&::-webkit-scrollbar { //4、父級盒子:隱藏滾動條(不兼容ios和微信端)
display: none;
}
padding-bottom: 100px; //5、通過padding-bottom將滾動條擠到盒子外
.body_content{
list-style: none;
width:2000px; //1、子級盒子:設置一個大的寬度,如2000,3000等
.every_content{
height:150px;
margin-right: 25px;
margin-bottom: 10px;
float: left; //6、展示內容的盒子,設置浮動
text-align: center;
}
}
}
}
}
}
</style>
實現一個固定區域內豎向滾動(不隱藏滾動條)
<div class="srollContent">
<ul>
<li>......</li>
<li>......</li>
</ul>
</div>
<style scoped lang="less">
.scrollContent{
height:300px; //固定父盒子高度
overflow-y:scroll; //超出部分會以滾動條形式展示
}
</style>
實現一個固定區域內豎向滾動(隱藏滾動條)
<div class="content"> //一級盒子
<div class="srollContent"> //二級盒子
<ul> //三級盒子
<li>......</li>
<li>......</li>
<li>......</li>
</ul>
</div>
</div>
<style scoped lang="less">
.content{
width:300px; //一級盒子固定寬度
overflow:hidden; //超出部分隱藏
.scrollContent{
width:500px; //二級盒子固定寬度,此寬度要比一級盒子大至少50px
height:300px; //二級盒子設置固定高度
overflow-y:scroll; // 二級盒子超出部分會以滾動條形式展示
ul{
width:300px; //三級盒子固定寬度,此寬度要比一級盒子小或相等
}
}
}
</style>
原理:滾動條在二級盒子超出一級盒子之外的部分。
這里一級盒子300px,二級500px,滾動條在200px那塊區間中
安利一個不錯的敘述vue移動端經驗的博客
https://www.cnblogs.com/wdlhao/p/9393539.html
v-if簡單使用
<li class="every_content" v-for="(item,index) in heros" :key="index">
<i v-if="item.type==0">我是亞索</i>
<i v-else-if="item.type==1">我是劍姬</i>
<i v-else-if="item.type==2">我是卡薩</i>
<i v-else-if="item.type==3">我是獅子狗</i>
</li>
左側圖片右側文字布局:圖片寬度固定的,現在要實現當屏幕寬度改變時,右側文字描述部分寬度自適應。
1、使用flex布局可以解決左右布局寬度自適應問題
2、但是flex布局時,若有文字溢出時展示省略號的需求,則需要配合overflow:hidden才可以
示例:
<div class="body">
<ul class="bodyContent">
<li class="everyContent" v-for="(item,index) in hotProductInfo" :key="index">
<div class="contentImg"><img :src="item.pictures"/></div> <!--左側圖片-->
<div class="contentDetails"> <!--右側文字描述-->
<div class="intro">{{item.intro}}</div>
</div>
</li>
</ul>
</div>
<style scoped lang="less">
.body{
.bodyContent{
.everyContent{
display: flex; //1、flex布局
.contentImg{
margin-right: 10px;
img{
width:140px;
height:80px;
}
}
.contentDetails{
flex:auto; //2、flex:1,auto都可以。右側文字描述部分寬度自適應
overflow: hidden; //3、這里使用overflow:hidden,解決"文字溢出省略號展示功能"失效的問題
.intro{
font-size: 16px;
color:#333333;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
}
}
}
}
</style>
Vue中使用vant-ui
1、安裝Vant-ui yarn add vant & npm install vant -D
2、安裝按需引入的babel插件 yarn add babel-plugin-import & npm install babel-plugin-import -D
3、在.babelrc文件(此文件在根目錄下)中添加配置
{
"plugins": [
"transform-vue-jsx",
"transform-runtime",
["import", { //將此代碼添加進plugins里
"libraryName": "vant",
"libraryDirectory": "es",
"style": true
}]
]
}
4、在main.js中按需引入
import {Button,Tag} from 'vant'; //注意import {Button,Tag} from 'vant'要在Vue.use(Button).use(Tag)之前。即 使用之前先引入
Vue.use(Button).use(Tag);
5、按照vant官網api使用即可
<van-button type="primary">按鈕</van-button>
配合vant-ui框架的List組件實現“上拉加載更多”功能 (懶加載)
1、引入List組件(上面有介紹,句不過多贅述了)
2、如何使用:看下方代碼
<template>
<div>
<!--【***①組件***】van-list用於監聽滾動事件及設置加載相關事宜-->
<van-list
v-model="loading"
:finished="finished"
finished-text="-- 沒有更多了 --"
@load="onLoad"
:immediate-check=false //初始化頁面時不檢查滾動位置
>
<!--這里寫html代碼-->
<ul class="universityInfo" >
<li class="everyInfo" v-for="(item,index) in universityList" :key="index">
<div class="infoName"><span>{{item.pname}}</span></div>
</li>
</ul>
</van-list>
</div>
</template>
<script>
import * as axios from 'axios'
import common from '../../kits/common.js'
export default {
name:"pUniversityList",
data(){
//【***②參數***】
return{
universityList:[], //請求到的數據
loading: false, //加載狀態
finished: false, //是否全部加載完畢
page:1, //接口的請求頁碼
pagesize:15, //每次請求數據數量,在設置:immediate-check=false后,pagesize最好設置大一點
}
},
created(){
this.getUniversityList();
},
methods:{
getUniversityList(){
axios.get(`${common.coper}/allCooperation?page=${this.page}&pagesize=${this.pagesize}`) //【***③請求***】動態設置請求的頁碼和數據數量
.then(res=>{
if(res.data.code==200){
this.loading = false //請求接口成功時設置加載狀態為false,【敲黑板,這里踩坑了,this.loading=false應該寫在這里見下方解釋】
if(res.data.data.list){ //因為不確定當沒有數據時,后端接口返回給你的data.list是[],還是null,嚴謹一點,這里最好做一個判斷。
this.universityList=this.universityList.concat(res.data.data.list); //將請求的數據合並到之前的數據上
//this.universityList=res.data.data.list.reverse().concat(this.universityList); //使數據倒敘排序
if(res.data.data.list.length<this.pagesize){ //當請求到的數據量小於請求的數據量時,說明數據已全部請求完畢
this.finished = true; //數據全部加載完畢
}
}else{
this.finished = true;
}
}
}).catch(err=>{})
}
//懶加載函數【***④函數***】
onLoad() {
let times=setTimeout(()=>{
this.page+=1 //每請求一次,頁面數+1
this.getUniversityList()
/*this.loading=false*/
//之前的this.loading=false是寫在這里的,導致了一個bug就是每次上拉頁面onload函數會執行兩次或多次。原因在於這里是異步執行,故this.loading=false不會立即執行,因此loading是true狀態,函數onload也一直在執行中。此時就會出現多次調用接口的情況。所以要把this.loading=false設置在接口函數(見上方)中。保證在接口調用成功后,this.loading=false,即加載完成。
clearTimeout(times) //執行完定時器后清除定時器
},500)
}
},
}
</script>
上拉加載項目使用模板
【①】html模板
<van-list
v-model="loading"
:finished="finished"
finished-text="-- 沒有更多了 --"
@load="onLoad"
:immediate-check=false
>
。。。。。。
</van-list>
【②】data參數設置
data(){
//【***②參數***】
return{
universityList:[],
loading: false,
finished: false,
page:1,
pagesize:15,
}
},
【③】請求接口動態設置page,pagesize等
getUniversityList(){
axios.get(`${common.coper}/allCooperation?page=${this.page}&pagesize=${this.pagesize}`)
.then(res=>{
if(res.data.code==200){
this.loading = false
if(res.data.data.list){
this.universityList=this.universityList.concat(res.data.data.list);
if(res.data.data.list.length<this.pagesize){
this.finished = true;
}
}else{
this.finished = true;
}
}
}).catch(err=>{})
},
【④】onload加載函數
onLoad() {
let times=setTimeout(()=>{
this.page+=1
this.getUniversityList()
clearTimeout(times)
},500)
}
路由傳值,取值(一個參數)
1、路由部分配置:如router.js頁面,在需要取值的頁面的路由上添加/:testid
{
path:'/pUniversity/pUniversityInfo/:testid', //添加/:testid
component:pUniversityInfo
},
2、傳值,在需要傳值的頁面(如列表頁)
<li class="everyInfo" v-for="(item,index) in universityList" :key="index">
<router-link :to="'/pUniversity/pUniversityInfo/'+item.testid" > //這里通過這種方式傳入id值,注意to需要v-bind綁定,另外注意 / 符號別少了
<div class="infoImg"><img :src="item.pimage" /></div>
<div class="infoName"><span>{{item.pname}}</span></div>
</router-link>
</li>
3、取值,在需要取值的頁面(如詳情頁)
data(){
return{
id:this.$route.params.testid //注意這里是$route而不是$router
}
},
路由傳值取值(多個參數,params方式)
1、路由頁面
{
path:'/video/videoScreen',
component:VideoScreen,
name:'VideoScreen', //params傳多個參數必須要給路由命名,再通過命名方式跳轉。
},
2、傳值頁面
methods:{
postData(){
this.$router.push({name:'VideoScreen',params:{cid:this.demoCid,sid:this.demoSid,eid:this.demoEid}}) //params傳多個值,只能通過name命名方式跳轉,不可通過path路徑方式
},
}
3、取值頁面
data(){
return{
getData:this.$route.params //取值
}
}
丶丶丶【敲黑板】params通過路由name傳值的方式有個缺點,就是在取值頁面刷新后,傳過來的值便被清空了。丶丶丶
4、上述問題解決辦法:
在路由頁面做如下改動
{
path:'/video/videoScreen/:cid/:sid/:eid', //這里在路由后面配置一下需要傳的參數即可,這樣參數就跟着路由被帶過來,不會被清空了
component:VideoScreen,
name:'VideoScreen',
},
路由傳值取值(多個參數,query方式)
1、路由頁面
{
path:'/video/videoScreen',
component:VideoScreen,
},
2、傳值頁面
methods:{
postData(){
this.$router.push({path:'/video/videoScreen',query:{cid:this.demoCid,sid:this.demoSid,eid:this.demoEid}}) //query傳多個值,只能通過path路徑方式跳轉,不可通過name命名方式
},
}
3、取值頁面
data(){
return{
getData:this.$route.query//取值
}
}
Vue中使用三目運算符
【1、直接使用】
<template>
<div>{{transIndex==1?"第一個":"第二個"}}</div>
</template>
<script>
export default{
data(){
return{
transIndex:1,
}
}
}
</script>
【2、在class中使用,用來動態綁定樣式】
<template>
<div>
<button id="1" class="start" :class="selectid==1?'active':''" @click="select($event)">開始</button> //注意這里active是屬性,要加引號,不然會報錯
<button id="2" class="stop" :class="selectid==2?'active':''" @click="select($event)">結束</button> //在class里使用三木運算符時class需要v-bind綁定
</div>
</template>
<script>
export default{
data(){
return{
selectid:1,
}
},
methods:{
select(e){
this.selectid=e.currentTarget.id //獲取當前元素的id值
}
}
}
</script>
vue通過js設置當前頁面最小高度等於屏幕高度
在mounted鈎子函數中設置
mounted(){
document.getElementById('demo').style.minHeight = window.innerHeight + 'px';
},
vant-ui動態設值
<template>
<div>
<van-popup v-model="menuShow" position="left" :duration="state" class="sideBarPop"> //這是vantui里的彈出層組件,duration不可直接設值(需要綁定才行),需要通過:duration="state"這種方式動態賦值,或者直接:duration="0.5"
<div>DEMO</div>
</van-popup>
</div>
</template>
<script>
export default{
data(){
state:0.5,
}
}
</script>
Vue中dom元素完全渲染完畢后再獲取一些數據--例子:文本超過三行后顯示展開收起功能。(知識點較多)
1、完全渲染完畢后獲取數據:watch對象配合Vue.nextTick方法
2、判斷文本是否超過三行:獲取文本高度,獲取行高,行數=文本高/行高
【dom,css部分代碼】
<template>
<div class="contentIntro">
<div class="intro" id="intro"><span>{{goodsList.info}}</span></div> //文本域
<div v-show="isOpenShow"> //是否顯示展開收起模塊
<span class="moreIntro" @click="openIntro" v-show="!isOpen">展開</span>
<span class="moreIntro" @click="closeIntro" v-show="isOpen">收起</span>
</div>
</div>
</template>
<style scoped lang="less">
.intro{
color:#6f6f6f;
font-size: 15px;
line-height: 22px; //一定要設置line-height,以便js部分獲取line-height數據
//下面設置超出部分用省略號表示
display: -webkit-box; //將此display改變即可使省略失效
-webkit-line-clamp: 4; //設定行數
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
}
.moreIntro{
float:right;
font-size: 15px;
color:#ff7700;
}
</style>
【script部分代碼】
<script>
import common from '../../common.js'
import * as axios from 'axios
data(){
isOpenShow:false, //是否顯示展開收起按鈕
personInfo:[], //個人信息
personIntro:null, //個人信息-描述
},
watch:{ //watch配合nextTick實現dom渲染完畢后監聽dom元素
personIntro:function(){
this.$nextTick(()=>{ //vue的nextTick方法,可以配合watch實現在對更新過后的dom的監聽。這里是要監聽【渲染完畢后】的文本高度和行高,所以使用這種方法
const elem=document.getElementById('intro')
const H=elem.offsetHeight //獲取整個文本域的高度
/* const h=elem.style.lineHeight */ //獲取文本的行高。這種方法只能獲取行內樣式里的樣式,無法獲取外聯樣式設置的樣式,有局限性,這里不適用。但使用方式簡單,有時可以用用。在移動端,內聯樣式是固定的,不會被編譯器轉化成rem等,沒法自動適配屏幕,所以這里我們要獲取外聯樣式,這樣才能達到適配的目的,此方法只能獲取內聯樣式是不行的。
const h=window.getComputedStyle(elem,null).getPropertyValue("line-height") //獲取文本的行高。window.getComputedStyle()方法可以獲取元素的樣式屬性,包括外聯和內聯樣式,局限性很小。
const lineNum=parseFloat(H/parseFloat(h)).toFixed(2) //因為h的結果是帶px單位的,所以這里要 parseFloat(h).toFixed(2) 轉換為數字形式並保留兩位小數。 lineNum=H/h的意思是行數=文本高度/行高
console.log(H)
console.log(h)
console.log(lineNum)
if(lineNum>3){ //行高大於3時,展開按鈕出現,若移動端不出現展開按鈕,可以將3設置小一點試試,如2.6,2.7
this.isOpenShow=true
}
})
}
},
methods:{
getPersonInfo(){
axios.get(`${common.personindex}/getCooperation?pid=${this.pid}`).then(res=>{
if(res.data.code==200){
this.personInfo=res.data.data
this.personIntro=res.data.data.pdetails //給personIntrof賦值以配合watch方法實現監聽
}
})
},
openIntro(){
this.isOpen=true //收起按鈕出現
document.getElementById("intro").style.display="block" //設置display,使得文本省略失效,從而展示所有文本
},
closeIntro(){
this.isOpen=false //展開按鈕出現
document.getElementById("intro").style.display="-webkit-box" //重新設置display,以...省略形式展示
}
}
</script>
給v-html中的標簽添加css樣式
解決方案1:在updated生命周期函數中,js動態配置樣式,代碼如下
updated() {
$('.msgHtmlBox').find('p').css('color', 'blue');
},
解決方案2:去掉style標簽中的scoped屬性
scoped屬性導致css僅對當前組件生效(用css3的屬性選擇器+生成的隨機屬性實現的),而html綁定渲染出的內容可以理解為是子組件的內容,子組件不會被加上對應的屬性,所以不會應用css.
解決方案3:寫樣式的時候添加 >>> 符號(注:若使用了less,則不能使用此方法)
<style scoped>
.msgHtmlBox >>> p{
color: blue;
}
</style>
input獲取焦點失去焦點(注意瀏覽器兼容問題)
原則上失去焦點是@blur,獲取焦點是@focus
但是蘋果safari瀏覽器不能很好的兼容@focus,所以移動端的話@focus最好用@click代替
js使input框獲取焦點document.getElementById("inputName").focus()
js使input框失去焦點document.getElementById("inputName").blur()
vant-ui里toast的使用
sendComment(){
this.$toast({
message:'評論發表成功',
duration:2000,
})
this.commentValue=''
this.inputSelect=false
},
input輸入框在呼出鍵盤后錯位
https://www.cnblogs.com/ljx20180807/p/9837748.html
圖片間隔處理方法(如5張圖片,屏幕一行放下2張,中間間隔10px,兩邊無間隔)
使用nth-child(odd),nth-child(2n)方式添加margin-right:10px樣式
注意看下方圖片,一個是中間有間隔,兩邊無間隔。一個是所有圖片右側均有間隔
實現短信驗證碼倒計時
<span v-show="show" @click="getCode">獲取驗證碼</span>
<span v-show="!show" class="count">{{count}} s</span>
data(){
return {
show: true,
count: '',
timer: null,
}
},
methods:{
getCode(){
const TIME_COUNT = 60;
if (!this.timer) {
this.count = TIME_COUNT;
this.show = false;
this.timer = setInterval(() => {
if (this.count > 0 && this.count <= TIME_COUNT) {
this.count--;
} else {
this.show = true;
clearInterval(this.timer);
this.timer = null;
}
}, 1000)
}
}
}
vue正則匹配(踩坑,不要用全局g)
inputuname() {
const pattern = /^[\w\u4e00-\u9fa5]{3,8}$/ //注意這里不要用g全局匹配,否則若其他地方有不符合該正則的,則表達式會一直返回false。
if (this.username.length==0) {
this.errname = false
}else if(pattern.test(this.username)==false){
this.errname = true
}else if(pattern.test(this.username)==true){
this.errname = false
}
},
input輸入框光標高度問題
IE:不管該行有沒有文字,光標高度與font-size大小一致
FF:該行沒有文字時,光標大小與input的 height 大小一致;該行有文字時,光標大小與font-size大小一致
chrome:有2種情況,①設置了line-height 該行沒有文字時,光標大小與input的 line-height 大小一致; 該行有文字時,光標大小從input頂部到文字底部
②沒有設置line-height 光標大小與font-size一樣
所以,input在使用的時候,最好不要設line-height, 可以設定一個較小的height, 然后用 padding 來撐開,這樣基本上可以解決所有瀏覽器的問題
input{
height: 10px;
padding: 10px 0px;
font-size: 12px;
}
使用vant的upload組件上傳頭像,圖片(上傳圖片使用form表單形式,而非json)
<template>
<div class="image">
<span>頭像:</span>
<van-uploader class="imgDiv" :after-read="afterRead">
<div class="uploaderStyle" v-if="!imgUrl">
<span>+</span>
<span>上傳頭像</span>
</div>
<div class="imageShow" v-if="imgUrl">
<img :src="imgUrl"/>
</div>
</van-uploader>
</div>
</template>
<script>
afterRead(file){
/* console.log(file.file) */
let param = new FormData(); //創建formData對象
param.append('file', file.file); //組件獲取到的圖片file有時需要經過處理后上傳,這里需要上傳file里面的file數據,所以file.file,見下圖
let config = {
headers: {
'Content-Type': 'multipart/form-data' //設置請求頭格式
}
};
axios.post(`${common.api}/upload`, param, config).then(res => { //上傳至 圖片處理接口 拿到后台處理過后的圖片url
if(res.data.code==200){
this.imgUrl=res.data.msg //這就是后台處理過后的url
axios.post(`${api.userApi}/demoimg?faceimg=${this.imgUrl}`).then(res=>{ //將處理過后的圖片url上傳至其他接口
if(res.data.code==200){
this.$toast("圖片上傳成功")
}
})
}
})
}
</script>
上傳圖片小結
這里上傳的方式是在vant組件的after-read文件讀取的鈎子函數里拿到圖片file,然后將file.file上傳到后台的圖片處理接口,再拿到處理接口返回的url,這時圖片就轉化成了url形式,再將這個url上傳給其他需要的接口即可。
即after-read讀取文件-->file傳處理接口-->拿到處理后url-->使用url傳其他接口
而需要說明的是並不是每個ui框架的上傳組件都是這種處理模式,有的框架的文件讀取是單獨出來的api(如vant的after-read)。
而有的文件讀取是內嵌在組件內部的,比如antDesign的文件讀取就在beforeUpload之中,element,mint,cube等每一個都有自己的模式。
如果框架沒有單獨的文件讀取api,可以參考 https://www.cnblogs.com/huihuihero/p/11060531.html 里的圖片上傳方式
vue根據不同數據動態設置背景
<div class="demo" :style="{background:'url('+require('../../assets/image/pic_'+(index+1)+'.png')+') no-repeat center'}"></div>
注意:圖片必須要以pic_1.png pic_2.png pic_3.png pic_4.png這種數字型命名