腳手架搭建css
// 安裝node、npm // 查看node版本 node -v // 查看npm版本 npm -v // 如未安裝請安裝node, node會一塊兒安裝npm // 全局安裝 vue-cli npm install vue-cli -g // 下載腳手架項目 vue init webpack my-project // 進入項目根目錄 cd my-project // 啓動服務 npm start 或 npm run dev // 訪問url localhost:8080 或 127.0.0.1:8080
補充:
點這裏 → node下載地址html
主體結構說明vue
├─build // webpack配置文件(如:路徑配置、css預編譯等) ├─config // vue配置文件(如:端口、打包輸出等) ├─dist // npm run dev打包後的文件夾 ├─node_modules // node安裝依賴包 ├─src // 資源文件夾 ├─assets // 靜態文件資源 ├─components // 組件文件夾(如:common公用組件、pages頁面組件) ├─router // 路由文件夾 ├─App.vue // vue入口文件 ├─main.js // 頁面程序入口文件 ├─static // 靜態資源(如:圖片、json數據等) ├─.babelrc // es6解析的配置 ├─.editorconfig // 編輯器統一代碼風格的配置 ├─.gitignore // git忽略提交的配置 ├─.postcssrc.js // css轉換的配置 ├─index.html // 頁面入口 ├─package-lock.json // node_modules 或 package.json 發生變化時自動生成的文件 ├─package.json // 項目基本信息 └─README.md // 項目說明 // config ├─config ├─dev.env.js // 開發環境配置 ├─index.js // 主配置 ├─prod.env.js // 生產環境配置 // build ├─build ├─build.js // npm run build構建生產版本 ├─check-versions.js // 檢測node和npm的版本,實現版本依賴 ├─utils.js // css預編譯處理工具 ├─vue-loader.conf.js // vue處理工具(template、script、style) ├─webpack.base.conf.js // 開發和生產共同使用的配置文件,主要實現配製入口,配置輸出環境,配置模塊resolve和插件等 ├─webpack.dev.conf.js // 開發環境webpack配置 ├─webpack.prod.conf.js // 生產環境webpack配置
端口node
// 更改端口 port: 3000,
打開瀏覽器webpack
// 是否在編譯完成後,自動打開瀏覽器訪問http://localhost:3000 autoOpenBrowser: false,
代理ios
proxyTable: { // 接口跨域 // 解決跨域的問題 '/lots-web/**': { target: 'http://localhost:8080' // 接口的域名 }, // 開發環境本地數據掛載 // json數據文件路徑:static/mock/index.json '/api': { target: 'http://localhost:7000', pathRewrite: { '^/api': '/static/mock' } } }
路徑配置git
alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src'), // import 'css/common.css' 'css': resolve('src/assets/css') }
variables.scss預編譯es6
// 安裝模塊: // npm install --save-dev sass-loader // npm install --save-dev node-sass // npm install --save-dev sass-resources-loader scss: generateLoaders('sass').concat( { loader: 'sass-resources-loader', options: { resources: path.resolve(__dirname, '../src/assets/css/variables.scss') } } ) // 使用方式:xxx.vue @import 'css/xxx.scss' <style lang='scss' scoped><style>
variables.styl預編譯web
// 安裝模塊: // npm install --save-dev stylus // npm install --save-dev stylus-loader const stylusOptions = { import: [ path.join(__dirname, "../src/assets/css/variables.styl") ] } return { stylus: generateLoaders('stylus', stylusOptions), styl: generateLoaders('stylus', stylusOptions) } // 使用方式:xxx.vue @import 'css/xxx.styl' <style lang='stylus' scoped><style>
初始 主文件vue-router
import Vue from 'vue' import App from './App' import router from './router' Vue.config.productionTip = false new Vue({ el: '#app', router, components: {App}, template: '' })
詳細 主文件
// 入口 import router from './router' // 路由 import store from './store' // 狀態 import api from './utility/api' // 接口 // 模塊 import axios from 'axios' // 接口調用 import 'babel-polyfill' // ie9和一些低版本的瀏覽器對es6新語法的不支持問題 import fastClick from 'fastclick' // 延遲300毫秒 import VueAwesomeSwiper from 'vue-awesome-swiper' // 圖片輪播 import BScroll from 'better-scroll' // 拖動插件 // 公用樣式 import 'css/reset.css' // 重置 import 'css/common.css' // 公共 import 'css/border.css' // 1像素邊 import 'css/iconfont.css' // 文字圖標 import 'swiper/dist/css/swiper.css' // 圖片輪播 // 公用組件 import Fade from '@/pages/common/fade' // 顯隱過渡 import Gallery from '@/pages/common/gallery' // 畫廊 Vue.component('c-fade', Fade) Vue.component('c-gallery', Gallery) // 全局調用 Vue.use(VueAwesomeSwiper) Vue.prototype.$scroll = BScroll Vue.prototype.$http = axios Vue.prototype.$api = api fastClick.attach(document.body) // 爲消除移動端瀏覽器,從物理觸摸到觸發點擊事件之間的300ms延時的問題 Vue.config.productionTip = false // 設置爲 false 以阻止 vue 在啓動時生成生產提示 // 建立Vue new Vue({ el: '#app', router, store, components: {App}, template: '<App/>' })
vue入口文件
keep-alive數據緩存
<keep-alive :exclude="exclude"> <router-view/> </keep-alive> data(){ return { exclude: [ 'Detail' ] } }
用法
// 一、如不填,則緩存所有組件 // 二、keep-alive include="City",緩存name='City'的組件 // 三、keep-alive exclude="Detail",不緩存name='Detail'的組件
生命週期
// 當時用keep-alive的時候,會觸發activated和deactivated生命週期 // activated 當組件被激活的時候調用 // deactivated 當組件被移除的時候調用
路由文件人口
初始 文件
import Vue from 'vue' import Router from 'vue-router' import Home from '@/pages/home/home' export default new Router({ routes: [ { path: '/home', component: Home } ] )}
詳細 文件
import Vue from 'vue' import Router from 'vue-router' import Home from '@/pages/home/home' const path = { home: '/' } const router = new Router({ // 路由和組件渲染 routes: [ { path: path.home, component: Home } ], // 路由"#"號去除 mode: 'history', // 當前路由添加.active linkActiveClass: 'active', linkExactActiveClass: 'active', // 切換路由時界面始終顯示頂部 scrollBehavior(to, from, savePosition){ return { x: 0, y: 0 } } )} export default router
狀態管理文件入口:index.js
// 狀態管理 import Vue from 'vue' import Vuex from 'vuex' import state from './state' import mutations from './mutations' import actions from './actions' Vue.use(Vuex) export default new Vuex.Store({ state, mutations, actions })
第一步 引入state.js
// state.js let defaultCity = { id: 1, spell: 'beijing', name: '北京' } if(localStorage.city){ defaultCity = JSON.parse(localStorage.city) // 字符串轉對象 } const state = { city: defaultCity } export default state
第二步 引入mutations.js
// mutations.js const mutations = { changeCity(state, payload){ state.city = payload localStorage.city = JSON.stringify(payload) // 當爲對象是,要轉字符串 } } export default mutations
第三步 引入actions.js
// actions.js const actions = { changeCity(context, payload){ context.commit('changeCity', payload) } } export default actions
第四步 vue文件使用vuex
// xxx.vue // template部分: <div @click="handleClick(item)">{{city}}</div> // script部分: import { mapState, mapActions} from 'vuex' export default { computed: { ...mapState(['city']) }, methods: { ...mapActions(['changeCity']) handleClick(city){} this.changeCity(city) } } }
$http調用接口
全局調用
// 修改main.js文件 Vue.prototype.$http = axios // xxx.vue文件: this.$http .get('/api/index.json', { params: {...} }) .then( fn(data) ).catch( fn(data ));
局部調用
// xxx.vue文件: import axios from 'axios' axios.get('/api/index.json') .then( fn(data) ) .catch( fn(data) );
示例
getHomeData() { this.$http .get(this.$api.home, { params: { name: this.city.name } }) .then(res => { let resData = res.data; if (resData.ret && resData.data) { let data = resData.data this.bannerList = data.bannerList this.iconList = data.iconList this.likeList = data.recommendList this.weekendList = data.weekendList } }) .catch((err) => { console.log(err) }) }
縮放比例
// 修改文件:index.html <meta minimum-scale=1.0, maximum-scale=1.0, user-scalable=no> <meta width="device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
移動端初始配置
// 移動端訪問 // 修改package.json文件:--host 0.0.0.0 // mac查看ip: ifconfig // windows查看ip: ipconfig // 手機訪問地址: ip地址:7000
初始化
// 初始化樣式 reset.css // 1px像素設備不一致 borer.css import 'css/common.css' // 公共 import 'css/border.css' // 1像素邊
延遲300ms
// 模塊 fastclick 解決移動端事件延遲300ms // main.js文件加入: import fastClick from 'fastclick' // 延遲300毫秒 fastClick.attach(document.body)
文字圖標
// 網址 http://www.iconfont.cn // 步驟 // 選擇圖標加入購物車 → // 添加到項目 → // 下載到本地 → // 字體和css複製到項目 → // 更改iconfont目錄和刪除代碼 → // 引入iconfont.css → <span class="iconfont user-icon">&#x e624;><span>
拖動使界面滾動
全局
// 修改main.js文件: import BScroll from 'better-scroll' Vue.prototype.$scroll= BScroll xxx.vue文件: mounted() { this.scroll = new this.$scroll(elevent); // element爲dom或$refs },
局部
// xxx.vue文件: import BScroll from 'better-scroll' this.scrolll = new BScroll(this.$refs.wrapper) // 定位到某個元素 this.scroll.scrollToElement(element)
圖片輪播
// 網址 https://www.swiper.com.cn/ // 步驟 // 安裝模塊 vue-awesome-swiper 輪播插件(2.6.7) // 修改main.js: import "swiper/dist/css/swiper.css" Vue.use(VueAwesomeSwiper) xxx.vue文件: <swiper :options="swiperOption" v-if="hasBanner"> <swiper-slide v-for="item in list"> <img :src="item.imgUrl"> </swiper-slide> <div class="swiper-pagination" slot="pagination"></div> </swiper> swiperOption: { pagination: '.swiper-pagination', autoplay: 3000, paginationType: 'fraction', loop: true }
路由連接
// router-link組件的active設置 // 全局設置: export default new VueRouter({ linkActiveClass: 'active', linkExactActiveClass: 'active', routes : [ ... 省略 ] }); // 局部設置: <router-link :to="'home'" tag="li" active-class="active" exact-active-class="active" exact><標題router-link> // 加上exact 則遵循路由徹底一致模式,該路由下的路徑不匹配 // 標準 <router-link :to="'/detail?name=' + item.name" tag="div"></router-link> // 路由跳轉 this.$router.push('/')、this.$router.replace('/')
過渡動畫
// template <transition> <slot></slot> </transition> // style <style lang="stylus" scoped> .v-enter, .v-leave-to opacity 0 .v-enter-active, .v-leave-active transition opacity .5s </style> // name name="fade" .fade-enter
拖動事件
// touchstart/touchmove <div class="letter" @click="handleClickLetter" @touchstart.prevent="handleTouchStart" @touchmove="handleTouchMove" ref="letter"> <div class="letter-cont" ref="letterCont"> <span class="letter-item" v-for="item in list" :key="item">{{item}}</span> </div> </div> methods: { handleClickLetter(e) { const letter = e.target.innerHTML this.$emit('change', letter) }, handleTouchStart() { this.letterHeight = this.$refs.letterCont.clientHeight / this.letterLen this.letterOffsetTop = this.$refs.letter.offsetTop + this.$refs.letterCont.offsetTop }, handleTouchMove(e) { let touchY = e.touches[0].clientY let letterScope = (touchY - this.letterOffsetTop) / this.letterHeight if (letterScope > 0 && letterScope < this.letterLen) { if (this.timer) clearTimeout(this.timer) this.timer = setTimeout(() => { this.letterIndex = Math.floor(letterScope) }, 16) } } }
組件裏name的做用
// 一、遞歸組件會用到 // 二、取消緩存的時候會用到 // 三、瀏覽器vue插件顯示組件的時候用到
子父組件傳值
// 子組件: handleClick(){ this.$emit('change', value) } // 父組件: <component @change="handleClick"></component> handleClick(){}
$refs
// this.$refs.msg 普通元素,引用指向dom: <div ref='msg'>Hello, world<div> // this.$refs.child 組件,引用指向組件實例: <c-child ref='child'>Hello, world<c-child>
$route獲取url數據
// 1. /detail/:id // /detail/1389435894 this.$route.params.id // 2. /detail // /detail?id=1389435894 this.route.query.id
利用setTimeout節流
if(this.timer) clearTimeout(timer); this.timer = setTimeout(()=>{ console.log(''xxx') }, 16);
滾動監聽
// 1. window.onscroll = this.handleScroll // 2. window.addEventListener('scroll', this.handleScroll)
瀏覽器cookie
localStorage.city = city localStorage.clear()