<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
--生成隨機id
yarn add nanoid
import {nanoid} from 'nanoid' var id = nanoid()
yarn add vue-router
router/index.js
import Vue from 'vue' import VueRouter from 'vue-router' Vue.use(VueRouter) import Movie from '../pages/Movie/index.vue' import Music from '../pages/Music/index.vue' const routes = [ { path:"/music", component:Music }, { path:"/movie", component:Movie } ] const router = new VueRouter({ routes, mode:"history" }) export default router;
import Vue from 'vue' import App from './App.vue' import router from './router' Vue.config.productionTip = false new Vue({ router, render: h => h(App), }).$mount('#app')
<template> <div> <router-view></router-view> </div> </template>
在main.js中掛載在Vue原型上
Vue.filter("handleStr",function(val){ if(val.length > 3){ val = val.slice(0,3) + '...' } return val })
安裝依賴
yarn add element-ui
main.js
.... import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css'; Vue.use(ElementUI); ...
import Loading from '../components/Loading.vue' Vue.component("Loading",Loading)
只在手機端
lib-flexible 阿里
yarn add lib-flexible postcss-pxtorem@5.1.1
新建postcss.config.js
module.exports = { plugins: { 'postcss-pxtorem': { rootValue: 75, propList: ['*'], }, }, };
匯入lib-flexible
import 'lib-flexible/flexible.js'
將此行註釋,關閉視口
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<template> <div id="app"> ... </div> </template>
<script> ... </script>
<style> *{ margin: 0; padding: 0; } #app{ width: 10rem; margin: 0 auto; background-color: red; } </style>
// #1 定義一個元件 <template> <transition> <slot name="fade"></slot> </transition> </template>
<script> export default { } </script>
<style> .v-enter,.v-leave-to{ opacity: 0; } .v-enter-active,.v-leave-active{ transition: opacity 4s; } </style>
// #2 使用 <template> <div class="about"> <Fade> <h1 slot="fade" v-show="isShow">This is an about page</h1> </Fade> </div> </template>
<script> import Fade from '../components/Fade.vue' export default { data() { return { isShow:true } }, components:{ Fade } } </script>
1、rem 2、asssreset.css
被選中的路由樣式
.router-link-active{ color: #ff2d51; }
– 在路由設定中增加一條meta屬性
const routes = [ { path: '/films', name: 'Films', component:Films, meta:{ isNav:true } }, { path: '/article', name: 'Article', component:Article, meta:{ isNav:true } }, { path: '/center', name: 'Center', component:Center, meta:{ isNav:true } }, { path:"/movie/:id", name:'MovieDetail', component:MovieDetail } ]
通過v-if動態顯示
<tab-bar v-if="this.$route.meta.isNav"></tab-bar>
this.$router.back()
yarn add vue-preview
import VuePreview from 'vue-preview' Vue.use(VuePreview)
yarn add vant babel-plugin-import
module.exports = { presets: [ '@vue/cli-plugin-babel/preset' ], plugins: [ ["import", { "libraryName": "vant", "libraryDirectory": "es", "style": true }] ] }
import {Button} from 'vant' Vue.use(Button)
router-view實現動畫
<template> <div> <div class="cover" v-if="isShow"></div> <transition @before-enter="handleBeforeEnter" @enter="handleEnter" > <slot></slot> </transition> </div> </template>
<script> /* .v-enter @before-enter .v-ernter-active @enter .v-enter-to @after-enter */ export default { data() { return { isShow:false } }, methods:{ handleBeforeEnter(){ this.isShow = true }, handleEnter(){ setTimeout(() => { this.isShow = false }, 200); } } } </script>
<style> .v-enter-active{ animation: animate 2s linear; } @keyframes animate { 0%{ opacity: 0; transform: translateY(0px); } 50%{ opacity: .5; transform: translateY(20px); } 100%{ opacity: 1; transform: translateY(0px); } } .cover{ width: 100%; height: 100%; background-color: #fff; position: fixed; z-index: 10; } </style>
{ path: '/films', name: 'Films', component:Films, meta:{ isNav:true }, children:[ { path:"nowPlaying", component:NowPlaying } ] },
需要加入router-view
<template> ... <div class="container"> <!-- 裝載父路由下的子路由的對應 --> <router-view></router-view> </div> </template>
--又稱路由懶載入
{ path: '/about', name: 'About', // 非同步路由 component: () => import(/* webpackChunkName: "about" */ '../views/About.vue') },
怎麼減少首屏渲染時間
1、使用非同步路由
--面試常客
1-1 A頁面初次載入
beforeCreate(){ console.log('beforeCreate'); }, created(){ console.log('created'); }, beforeMount(){ console.log('beforeMount'); }, mounted(){ console.log('mounted'); },
1-2 A->B
從A頁面跳轉到B頁面
A頁面觸發以下生命週期
beforeDestroy(){ console.log('beforeDestroy'); }, destroyed(){ console.log('destroyed'); }
1-3 B–>A
從B頁面回到A頁面
A頁面觸發以下生命週期
beforeCreate(){ console.log('beforeCreate'); }, created(){ console.log('created'); }, beforeMount(){ console.log('beforeMount'); }, mounted(){ console.log('mounted'); },
upDate
beforeUpdate , beforeUpdate執行需要滿足以下兩個條件
1、data中的資料更新的時候
2、模板中要使用data中的資料
destroyed
# A頁面 --> b頁面
b頁面執行以下生命週期:
只能在mounted生命週期中獲取DOM
localStorage.setItem() 函數會將物件或者陣列全部轉換成字串的形式
所以可以對快取進行判斷,使用 JSON.stringify 和 JSON.parse 分別處理資料
const setLocalStorage = (key , value) => { if(value instanceof Array || value instanceof Object){ value = JSON.stringify(value) } localStorage.setItem(key , value) } const getLocalStorage = (key) =>{ var val = localStorage.getItem(key) var reg = /^[[{].*[]}]/ if(reg.test(val)){ val = JSON.parse(val) } return val }
安裝依賴
yarn add axios-jsonp
axios格式
import axios from 'axios' import jsonpAdapter from 'axios-jsonp' axios({ url:"", adapter: jsonpAdapter, }).then( res => console.log(res) )
騰訊地圖api需要在最後加上 &output=jsonp
https://apis.map.qq.com/ws/location/v1/ip?key=L6UBZ-JSLCU-FRAVA-4DBQG-V5WC5-2RBJ4&output=jsonp
http://47.108.197.28:3000/top/playlist?limit=1&offset=1
在小程式中
wx.request({ })
axios中
import axios from 'axios' axios({ url:"http://47.108.197.28:3000/top/playlist", method:"get", params:{ limit:1 } }).then(res=>{ console.log(res) })
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { }, mutations: { }, actions: { }, modules: { } })
--state中存放的是資料
state: { num:10 }
this.$store.state
--mutation中的函數第一個預設引數是state
--連線方式 commit
mutations: { add(state){ console.log(state); state.num++; } },
this.$store.commit('add')
--actions中的函數第一個預設值是上下文
--連線方式 dispatch
actions: { addNum(ctx){ console.log(ctx); ctx.commit("add") } },
this.$store.dispatch('a')
路由元件的兩個生命週期函數
/* 路由元件被啟用時觸發。 */ activated(){ console.log('activated') } /* 路由元件失活時觸發。 */ deactivated(){ console.log('deactivated') }
全域性路由守衛
router.beforeEach((to , from ,next)=>{ console.log(to); // 要跳轉的路由 console.log(from); // 起點路由 next(); })
<template> <div> <el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm" > <!-- props為了規則校驗 rules --> <el-form-item label="使用者名稱" prop="username"> <el-input type="text" v-model.number="ruleForm.username"></el-input> </el-form-item> <el-form-item label="密碼" prop="pass"> <el-input type="password" v-model="ruleForm.pass" autocomplete="off" ></el-input> </el-form-item> <el-form-item label="確認密碼" prop="checkPass"> <el-input type="password" v-model="ruleForm.checkPass" autocomplete="off" ></el-input> </el-form-item> <el-form-item> <el-button type="primary" @click="submitForm('ruleForm')" >提交</el-button > <el-button @click="resetForm('ruleForm')">重置</el-button> </el-form-item> </el-form> </div> </template> <script> export default { // beforeRouteEnter () { // /* 在區域性守衛中獲取不到this */ // console.log(1); // }, data() { var checkUsername = (rule, value, callback) => { if (!value) { return callback(new Error("使用者名稱不能為空")); }else{ callback(); } }; var validatePass = (rule, value, callback) => { if (value === "") { callback(new Error("請輸入密碼")); } else { if (this.ruleForm.checkPass !== "") { this.$refs.ruleForm.validateField("checkPass"); } callback(); } }; var validatePass2 = (rule, value, callback) => { if (value === "") { callback(new Error("請再次輸入密碼")); } else if (value !== this.ruleForm.pass) { callback(new Error("兩次輸入密碼不一致!")); } else { callback(); } }; return { ruleForm: { pass: "", checkPass: "", username: "", }, rules: { pass: [{ validator: validatePass, trigger: "blur" }], checkPass: [{ validator: validatePass2, trigger: "blur" }], username: [{ validator: checkUsername, trigger: "blur" }], }, }; }, methods: { submitForm(formName) { this.$refs[formName].validate((valid) => { if (valid) { // alert("submit!"); // console.log(this.ruleForm); // console.log(username,pass); /* 傳送http請求 */ this.loginHttp() } else { console.log("error submit!!"); return false; } }); }, resetForm(formName) { this.$refs[formName].resetFields(); }, loginHttp(){ var {username , pass} = this.ruleForm this.$http({ method: 'post', url:'http://localhost:8000/login', data:{ username, pass } }).then(res=>{ console.log(res.data); if(res.data.code == 200){ this.$message({ message:res.data.msg, type:"success", duration:1000 }) this.$router.push('/home') }else{ this.$message({ message:res.data.msg, type:"warning", duration:1000 }) } }) } } }; </script>
const koa = require("koa"); const app = new koa(); const koaBody = require("koa-body"); const router = require("koa-router")(); const cors = require("koa2-cors"); /* username=cheng pass=123456 */ console.log(ctx.request.body); var {username , pass } = ctx.request.body if(username == "cheng" && pass == "123456"){ ctx.cookies.set("loginAuth",true,{ /* httpOnly:false 設定前端可讀 */ httpOnly:false }) ctx.body = { code:200, msg:"登入成功" } }else{ ctx.body = { code:400, msg:"登入失敗,使用者名稱或密碼錯誤" } } }) /* 後端設定cookie可以實現跨域存取 */ app.use(cors({ origin:ctx =>{ return ctx.headers.origin }, credentials:true })); app.use(koaBody()); app.use(router.routes()); app.listen(8000);
3-1 設定後端cookie可以存取
/* 後端設定cookie可以實現跨域存取 */ app.use(cors({ origin:ctx =>{ return ctx.headers.origin }, credentials:true }));
3-2 設定前端跨域存取cookie
import axios from 'axios' /* 設定前端跨域存取cookie */ axios.defaults.withCredentials = true axios.defaults.crossDomain = true
3-3 vue上獲取cookie
安裝依賴
yarn add vue-cookie
設定main.js
import VueCookie from 'vue-cookie' Vue.use(VueCookie)
在頁面中獲取cookie
mounted() { console.log(this.$cookie.get('loginAuth')); }
3-4 路由守衛
--沒有登入的情況下,不能進入其它頁面
--已經登入的情況下,直接進入首頁
var vm = new Vue(); router.beforeEach((to,from,next)=>{ console.log(vm.$cookie.get('loginAuth')); var isLogin = vm.$cookie.get('loginAuth') if(to.path == "/login"){ /* 1、登入頁面,如果cookie顯示登入了直接進入home頁面,如果沒有登入,正產執行login頁的邏輯 */ if(isLogin){ router.push('/home') }else{ next() } }else{ /* 2、在其他頁面,如果登入正常顯示,沒有登入則停留在login頁面 */ if(isLogin){ next() }else{ router.push('/login') } } })
安裝依賴
yarn add vue-lazyload
在main.js中進行設定
import VueLazyLoad from 'vue-lazyload' Vue.use(VueLazyLoad,{ preLoad:1.3, loading:require('@/assets/loading.gif') })
使用(將:src替換成v-lazy)
<template> <div class="home"> <div v-for="item of playlists" :key="item.id"> <img class="item" v-lazy="item.coverImgUrl" alt=""> <p>{{item.name}}</p> </div> </div> </template>
--實現loading的載入效果
在vuex中定義一條isShowLoading --> 設定載入條是否顯示
export default new Vuex.Store({ state: { isSowLoading:true }, })
main.js
// 設定 請求攔截 和 響應攔截 // 新增請求攔截器 axios.interceptors.request.use(function (config) { // 在傳送請求之前做些什麼 store.state.isSowLoading = true return config; }); // 新增響應攔截器 axios.interceptors.response.use(function (response) { // 2xx 範圍內的狀態碼都會觸發該函數。 // 對響應資料做點什麼 store.state.isSowLoading = false return response; });
App.vue設定loading
<template> <div id="app"> <Loading v-if="this.$store.state.isShowLoading"/> <router-view/> </div> </template>
vant-ui 中整合了小程式中的 onBottom 和 onLoad
<template> <div class="home"> <van-list class="home" v-model="loading" :finished="finished" finished-text="沒有更多了" @load="onLoad" > <van-cell @click="handleClick(item.id)" v-for="item of playlists" :key="item.id"> <img class="item" v-lazy="item.coverImgUrl" alt=""> <p>{{item.name}}</p> </van-cell> </van-list> </div> </template>
<script> export default { name: 'Home', data() { return { playlists:[], loading:false, finished:false } }, mounted() { }, methods: { onLoad(){ setTimeout(()=>{ var offset = this.playlists.length console.log(1); this.axios.get(`http://47.108.197.28:3000/top/playlist?offset=${offset}&limit=20`).then(res =>{ var playlists = this.playlists.concat(res.data.playlists) this.playlists = playlists this.loading = false }) },500) }, handleClick(id){ this.$router.push(`detail?id=${id}`) } }, } </script>
<style scoped> .item{ width: 150px; height: 150px; } .home{ display: flex; justify-content: space-between; flex-wrap: wrap; } .van-cell{ width: 150px; } .home >>> .van-list__loading{ position: fixed; bottom: 0; left: 50%; transform:translateX(-50%); } </style>
在路由設定中,重置卷軸的x,y
const router = new VueRouter({ ... scrollBehavior (to , from , savedPosition) { if( to.path == "/detail"){ return {x:0,y:0} // 讓頁面出於頂部 }else{ return savedPosition // 讓頁面出於記錄點 } } })
專案中遇到如下報錯內容:
Uncaught (in promise) Error: Redirected when going from “/XXX” to “/XXX” via a navigation guard.
原因:vue-路由版本更新產生的問題,導致路由跳轉失敗丟擲該錯誤,但並不影響程式功能
在main.js中改變push原型
import Router from 'vue-router' const originalPush = Router.prototype.push Router.prototype.push = function push(location, onResolve, onReject) { if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject) return originalPush.call(this, location).catch(err => err) }
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45