vue開(kāi)發(fā)移動(dòng)端h5環(huán)境搭建的全過(guò)程
技術(shù)選型
公司現(xiàn)在需要開(kāi)發(fā)移動(dòng)端的h5,使用現(xiàn)在比較流行的vue 2.0開(kāi)發(fā),使用的腳手架是Vant2,網(wǎng)絡(luò)訪問(wèn)使用的是axios,路由跳轉(zhuǎn)使用的是vue-router,開(kāi)發(fā)工具是vscode,作為一個(gè)安卓開(kāi)發(fā)程序員,對(duì)vue是不熟悉的,好在把環(huán)境搭建起來(lái)了,通過(guò)博客記錄一下
環(huán)境搭建
引入庫(kù)
我這里已經(jīng)安裝好了nodejs,并且已經(jīng)配置好了淘寶鏡像
npm config set registry https://registry.npm.taobao.org
這些配置網(wǎng)上都有,可以自行查詢。
vscode不能直接在工具里創(chuàng)建項(xiàng)目,要先創(chuàng)建一個(gè)空文件夾,然后通過(guò)vscode打開(kāi)文件夾。
在E:\vueProject文件夾下創(chuàng)建VueForBlog文件夾,使用vscode打開(kāi)(vscode默認(rèn)只能打開(kāi)一個(gè)項(xiàng)目,如果想打開(kāi)多個(gè),可以使用ctrl+shift+n),點(diǎn)擊工具欄終端,新建終端,正式開(kāi)始創(chuàng)建項(xiàng)目
終端輸入
npm i vant@latest-v2 -S
再輸入
npm install -g @vue/cli
安裝完成
打開(kāi)package.json看一下依賴
創(chuàng)建一個(gè)項(xiàng)目
vue create first-vue
這個(gè)好像不能用駝峰,我剛開(kāi)始用firstVue就報(bào)錯(cuò)。一般會(huì)出現(xiàn)選擇項(xiàng),我這邊選擇了vue2
創(chuàng)建完成以后,會(huì)是這個(gè)樣子
記住,后邊要cd到工程里,否則還是在工程外創(chuàng)建引用之類的
下邊用同樣的方法,引入axios,router,還有vant需要使用的 postcss-px-to-viewport,postcss-pxtorem,lib-flexible
npm install vue-router@3.0.7 npm install axios npm i -S amfe-flexible npm install postcss postcss-pxtorem --save-dev npm install postcss-px-to-viewport --save-dev npm install --save less-loader less
配置環(huán)境
配置vant 的基礎(chǔ)樣式,方便引用vant的組件。在first\src\assets\style\下創(chuàng)建theme.less,內(nèi)容
// Color Palette @black: #000; @white: #fff; @gray-1: #f7f8fa; @gray-2: #f2f3f5; @gray-3: #ebedf0; @gray-4: #dcdee0; @gray-5: #c8c9cc; @gray-6: #969799; @gray-7: #646566; @gray-8: #323233; @red: #ee0a24; @blue: #1989fa; @orange: #ff976a; @orange-dark: #ed6a0c; @orange-light: #fffbe8; @green: #07c160; // Gradient Colors @gradient-red: linear-gradient(to right, #ff6034, #ee0a24); @gradient-orange: linear-gradient(to right, #ffd01e, #ff8917); // Component Colors @text-color: @gray-8; @active-color: @gray-2; @active-opacity: 0.7; @disabled-opacity: 0.5; @background-color: @gray-1; @background-color-light: #fafafa; @text-link-color: #576b95; // Padding @padding-base: 4px; @padding-xs: @padding-base * 2; @padding-sm: @padding-base * 3; @padding-md: @padding-base * 4; @padding-lg: @padding-base * 6; @padding-xl: @padding-base * 8; // Font @font-size-xs: 10px; @font-size-sm: 12px; @font-size-md: 14px; @font-size-lg: 16px; @font-weight-bold: 500; @line-height-xs: 14px; @line-height-sm: 18px; @line-height-md: 20px; @line-height-lg: 22px; @base-font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Helvetica, Segoe UI, Arial, Roboto, 'PingFang SC', 'miui', 'Hiragino Sans GB', 'Microsoft Yahei', sans-serif; @price-integer-font-family: Avenir-Heavy, PingFang SC, Helvetica Neue, Arial, sans-serif; // Animation @animation-duration-base: 0.3s; @animation-duration-fast: 0.2s; @animation-timing-function-enter: ease-out; @animation-timing-function-leave: ease-in; // Border @border-color: @gray-3; @border-width-base: 1px; @border-radius-sm: 2px; @border-radius-md: 4px; @border-radius-lg: 8px; @border-radius-max: 999px;
同樣目錄下,創(chuàng)建一個(gè)public.css,內(nèi)容
body { background-color: #f8f8f9; min-height: 100vh; min-width: 100vw; } .padding-lr10 { padding: 0 10px; } .phoneContant header .van-nav-bar { text-align: center; line-height: 56px; background: #68c2bd; } h3 { font-size: 16px; } .phoneContant header .van-nav-bar .van-icon { font-size: 20px; color: #fff; } .phoneContant header .van-nav-bar__title { color: #fff; } .contant { padding: 0 10px; } .re { position: relative; } .cardContant { background: #f5f5f5; height: 78vh; width: 100%; clear: both; padding: 8px 0; } .hosImg { width: 60px !important; height: 60px !important; border-radius: 50%; }
這里的內(nèi)容,是根據(jù)項(xiàng)目中需要的樣式自定義的
在vue.config.js里進(jìn)行配置
css: { loaderOptions: { less: { lessOptions: { modifyVars: { // 或者可以通過(guò) less 文件覆蓋(文件路徑為絕對(duì)路徑) hack: `true; @import "@/assets/style/theme.less";`, }, }, }, }, },
訪問(wèn)資源路徑,有個(gè)快捷方法,設(shè)置一個(gè)符號(hào),用來(lái)直接指定到src目錄下,比用.
或者..
方便,還不容易出錯(cuò),同樣在vue.config.js里,@
就代表src目錄
chainWebpack: (config) => { config.resolve.alias.set("@", resolve("src")); config.plugin("html").tap((args) => { args[0].minify = false; return args; }); },
vue.config.js全部?jī)?nèi)容
const path = require("path"); // const CompressionWebpackPlugin = require("compression-webpack-plugin"); // // 定義壓縮文件類型 // const productionGzipExtensions = ["js", "css"]; // let timeStamp = new Date().getTime(); function resolve(dir) { return path.join(__dirname, dir); } module.exports = { // 基本路徑 publicPath: "./", // 輸出文件目錄 不寫則默認(rèn)根目錄 outputDir: "dist", assetsDir: "static", // 靜態(tài)資源目錄 (js, css, img, fonts) lintOnSave: false, // eslint-loader 是否在保存的時(shí)候檢查 // lintOnSave: 'error', // devServer: { // // development server port 8000 // port: 8000, // // If you want to turn on the proxy, please remove the mockjs /src/main.jsL11 // proxy: { // '/api/': { // target: process.env.VUE_APP_APIUrl, // changeOrigin: true // } // } // }, // /assets/style/public.css.less css: { loaderOptions: { less: { lessOptions: { modifyVars: { // 或者可以通過(guò) less 文件覆蓋(文件路徑為絕對(duì)路徑) hack: `true; @import "@/assets/style/theme.less";`, }, }, }, }, }, devServer: { // 設(shè)置主機(jī)地址 // 設(shè)置默認(rèn)端口 port: 8080, // // 設(shè)置代理 // proxy: { // "/": { // // target: "http://198.166.21.56:8080/", // ws: true, // 支持ws協(xié)議;websocket的縮寫; // changeOrigin: true, // 是否跨域 // pathRewrite: { // // 路徑替換 // "^/api": "", // }, // }, // }, }, // use the full build with in-browser compiler? // https://vuejs.org/v2/guide/installation.html#Runtime-Compiler-vs-Runtime-only // compiler: false, // webpack配置 // see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md webpack鏈接API,用于生成和修改webapck配置 //部署打包html帶引號(hào) chainWebpack: (config) => { config.resolve.alias.set("@", resolve("src")); config.plugin("html").tap((args) => { args[0].minify = false; return args; }); }, //壓縮打包文件大小 configureWebpack: (config) => { if (process.env.NODE_ENV === "Production") { // config.output.filename = `assets/js/[name].${timeStamp}.js`; // config.output.chunkFilename = `assets/js/[name].${timeStamp}.js`; config.plugins.push( new CompressionWebpackPlugin({ algorithm: "gzip", test: new RegExp("\\.(" + productionGzipExtensions.join("|") + ")$"), threshold: 10240, minRatio: 0.8, }) ); } config.externals = { // 'vue': 'Vue', // 'vuex': 'Vuex', // 'vue-router': 'VueRouter', // 'element-ui': 'ELEMENT', // 'Axios': 'axios', // 'jquery': '$', // 'moment': 'moment', // 'js-cookie': 'Cookies', // 'echarts': 'echarts', // 'tinymce/tinymce': 'tinymce' }; // } }, // configureWebpack: (config) => {// webpack配置,值位對(duì)象時(shí)會(huì)合并配置,為方法時(shí)會(huì)改寫配置 // if (debug) { // 開(kāi)發(fā)環(huán)境配置 // config.devtool = 'cheap-module-eval-source-map' // } else { // 生產(chǎn)環(huán)境配置 // } // Object.assign(config, { // 開(kāi)發(fā)生產(chǎn)共同配置 // resolve: { // alias: { // '@': path.resolve(__dirname, './src')//設(shè)置路徑別名 // //... // } // } // }) // }, // vue-loader 配置項(xiàng) // https://vue-loader.vuejs.org/en/options.html // vueLoader: {}, // 生產(chǎn)環(huán)境是否生成 sourceMap 文件 productionSourceMap: false, // css相關(guān)配置 配置高于chainWebpack中關(guān)于css loader的配置 // css: { // // 是否使用css分離插件 ExtractTextPlugin // extract: true, // // 開(kāi)啟 CSS source maps?是否在構(gòu)建樣式地圖,false將提高構(gòu)建速度 // sourceMap: false, // // css預(yù)設(shè)器配置項(xiàng) // loaderOptions: {}, // // 啟用 CSS modules for all css / pre-processor files. // modules: false // }, // use thread-loader for babel & TS in production build // enabled by default if the machine has more than 1 cores 構(gòu)建時(shí)開(kāi)啟多進(jìn)程處理babel編譯 //parallel: require('os').cpus().length > 1, // 是否啟用dll // See https://github.com/vuejs/vue-cli/blob/dev/docs/cli-service.md#dll-mode // dll: false, // PWA 插件相關(guān)配置 // see https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa //pwa: {}, // webpack-dev-server 相關(guān)配置 // devServer: { // open: process.platform === 'darwin', // host: '0.0.0.0', // port: 8080, // https: false, // hotOnly: false, // proxy: null, // 設(shè)置代理 // before: app => { } // }, // 第三方插件配置 pluginOptions: { // ... }, };
lintOnSave: false,
這個(gè)的意思就是關(guān)閉語(yǔ)法檢查,要不然會(huì)很多報(bào)錯(cuò),運(yùn)行不起來(lái)
在first-vue目錄下,新建一個(gè).postcssrc.js,在里邊配置postcss
module.exports = { plugins: { //... autoprefixer: { browsers: ["Android >= 4.0", "iOS >= 7"], }, "postcss-pxtorem": { rootValue: 37.5, //vant-UI的官方根字體大小是37.5 propList: ["*"], }, }, };
底部安全區(qū)適配
在public目錄下的index.html文件配置底部安全區(qū)適配
<!DOCTYPE html> <html lang="en"> <head> <meta base="/" id="base" /> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover,user-scalable=no" /> <link rel="icon" href="<%= BASE_URL %>favicon.ico" rel="external nofollow" /> <title>首頁(yè)</title> </head> <body> <!-- 開(kāi)啟頂部安全區(qū)適配 --> <van-nav-bar safe-area-inset-top /> <div id="app"></div> <!-- built files will be auto injected --> <!-- 開(kāi)啟底部安全區(qū)適配 --> <van-number-keyboard safe-area-inset-bottom /> </body> </html> <script> </script>
src目錄下,新建router目錄,下邊新建index.js,對(duì)router進(jìn)行配置
import Vue from "vue"; //路由 import VueRouter from "vue-router"; import { asyncRouterMap } from "@/config/router.config"; Vue.use(VueRouter); const routes = [] const router = new VueRouter({ routes: routes.concat(asyncRouterMap), mode: "hash", }); export default router;
在src的config目錄下,新建router.config,這個(gè)對(duì)應(yīng)路由和相應(yīng)的頁(yè)面
export const asyncRouterMap = [ { path: "/", component: () => import("@/components/Header.vue"), meta: { title: "首頁(yè)" }, // redirect: '/dashboard/workplace', redirect: "/home", children: [ { path: "/home", name: "home", component: () => import("@/views/Home.vue"), hidden: true, meta: { title: "首頁(yè)" }, }, { path: "/second", name: "second", component: () => import("@/views/Second.vue"), hidden: true, meta: { title: "第二頁(yè)" }, }, ], }, { path: "*", redirect: "/home", hidden: true, }, ];
具體頁(yè)面,等會(huì)創(chuàng)建
對(duì)App.vue進(jìn)行修改
<template> <div id="app"> <router-view></router-view> </div> </template> <script> export default { name: 'App', } </script> <style> #app { height: 100%; } .el-header, .el-footer { background-color: #b3c0d1; color: #333; text-align: center; line-height: 60px; } body > .el-container { margin-bottom: 40px; } </style>
我現(xiàn)在需要對(duì)一個(gè)頭部組件進(jìn)行封裝,因?yàn)槊總€(gè)頁(yè)面都有頭部導(dǎo)航欄,所以封裝成一個(gè)組件
在components目錄里,新建Header.vue
<template> <div class="phoneContant"> <header> <van-nav-bar class="personheader" :fixed="true" :placeholder="true" :safe-area-inset-top="true" :title="$route.meta.title" left-text="" :left-arrow="true" @click-left="back" /> </header> <router-view></router-view> </div> </template> <script> var config = { isAndroid: /Android/i.test(navigator.userAgent), //判斷是否為移動(dòng)端 isIos: !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //判斷是否為IOS }; export default { name: "Headers", //import引入的組件需要注入到對(duì)象中才能使用 components: {}, data() { //這里存放數(shù)據(jù) return { title: "", }; }, //監(jiān)聽(tīng)屬性 類似于data概念 computed: {}, //監(jiān)控data中的數(shù)據(jù)變化 watch: { $route: { handler(newRouter, fromRouter) { }, immediate: true, }, }, //方法集合 methods: { back() { this.$router.go(-1); return false; }, }, //生命周期 - 創(chuàng)建完成(可以訪問(wèn)當(dāng)前this實(shí)例) created() { let cont = window.history.length; console.log("window.history.length-----------------roomstep"); console.log(cont); }, //生命周期 - 掛載完成(可以訪問(wèn)DOM元素) mounted() { }, beforeCreate() {}, //生命周期 - 創(chuàng)建之前 beforeMount() {}, //生命周期 - 掛載之前 beforeUpdate() {}, //生命周期 - 更新之前 updated() {}, //生命周期 - 更新之后 beforeDestroy() {}, //生命周期 - 銷毀之前 destroyed() { }, //生命周期 - 銷毀完成 activated() {}, //如果頁(yè)面有keep-alive緩存功能,這個(gè)函數(shù)會(huì)觸發(fā) }; </script>
在main.js里進(jìn)行引入vant和css樣式,以及其他組件
import Vue from 'vue' import App from './App.vue' import "@/assets/style/public.css"; import router from "@/router"; import Vant from "vant"; import "vant/lib/index.less"; import "@/assets/style/public.css"; Vue.config.productionTip = false Vue.use(Vant); new Vue({ router, render: h => h(App), }).$mount('#app')
在src下創(chuàng)建一個(gè)views文件夾,新建兩個(gè)vue,Home.vue和Second.vue,內(nèi)容很簡(jiǎn)單
Home.vue
<template> <div class="phoneContant"> <van-button type="warning" @click="goToNext">進(jìn)入下一頁(yè)</van-button> </div> </template> <script> export default { name: "Home", data() { return { msg: "我是首頁(yè)", }; }, methods: { goToNext() { this.$router.push("/second"); }, }, }; </script> <style> </style>
Second.vue
<template> <div> {{msg}} </div> </template> <script> export default { data(){ return{ msg:"第二頁(yè)" } } } </script> <style> </style>
運(yùn)行
命令行輸入
npm run serve
沒(méi)問(wèn)題的話,就能運(yùn)行起來(lái)了。如果想要中斷運(yùn)行,終端里邊用ctrl+c快捷鍵
網(wǎng)絡(luò)封裝
對(duì)axios進(jìn)行封裝一下,方便使用。在src下新建utils文件夾,utils下新建request.js,
import axios from "axios"; import { Notify } from "vant"; import router from "@/router"; const baseURL =BaseUrl // process.env.NODE_ENV === "development" ? "/api" : window.productionUrl; //創(chuàng)建axios實(shí)例 const service = axios.create({ baseURL, // api的base_url window.productionUrl withCredentials: true, timeout: 30000, // 請(qǐng)求超時(shí)時(shí)間 }); // 發(fā)送請(qǐng)求攔截器 service.interceptors.request.use( (config) => { const Nonce = Math.ceil(+new Date() / 1000) + "" + Math.ceil(Math.random() * 10000); const CurTime = Math.floor(+new Date() / 1000).toString(); config.headers["Content-Type"] = "application/json;charset=UTF-8"; return config; }, (error) => { return Promise.reject(error); } ); //發(fā)送請(qǐng)求響應(yīng)攔截 service.interceptors.response.use( (response) => { const res = JSON.parse(CryptoJS.decrypt(response.data)); // 錯(cuò)誤的status情況 // console.log(res); if (!res.result) { Notify({ type: "danger", message: res.message || "error" }); return Promise.reject(res.message || "error"); } else { return res; } }, (error) => { Notify({ type: "danger", message: error.message || "error" }); return Promise.reject(error); } ); export default service;
結(jié)語(yǔ)
現(xiàn)在只是搭建了工程,如果沒(méi)有缺少步驟的話,應(yīng)該是可以運(yùn)行起來(lái)的,剩下的還有很多工作要做。。。
補(bǔ)充
之前的工程創(chuàng)建方式順序應(yīng)該錯(cuò)了,不是先創(chuàng)建文件夾,然后再用vscode打開(kāi),再執(zhí)行vue create命令,這樣的話,主目錄下,就會(huì)有子目錄,子目錄就是項(xiàng)目名。如果想主目錄就是項(xiàng)目,要現(xiàn)在需要?jiǎng)?chuàng)建工程的地方,打開(kāi)cmd命令行,執(zhí)行命令,然后用vscode打開(kāi)
總結(jié)
到此這篇關(guān)于vue開(kāi)發(fā)移動(dòng)端h5環(huán)境搭建的文章就介紹到這了,更多相關(guān)vue移動(dòng)端h5環(huán)境搭建內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue $set 給數(shù)據(jù)賦值的實(shí)例
今天小編就為大家分享一篇vue $set 給數(shù)據(jù)賦值的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-11-11VUE使用axios調(diào)用后臺(tái)API接口的方法
這篇文章主要介紹了VUE使用axios調(diào)用后臺(tái)API接口的方法,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-08-08Vue2項(xiàng)目升級(jí)到Vue3的詳細(xì)教程
看到好多開(kāi)源項(xiàng)目都升級(jí)了vue3,下面這篇文章主要給大家介紹了關(guān)于Vue2項(xiàng)目升級(jí)到Vue3的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-01-01vue3 component is 不顯示的問(wèn)題及解決
這篇文章主要介紹了vue3 component is 不顯示的問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03vue項(xiàng)目打包后瀏覽器緩存問(wèn)題及解決
這篇文章主要介紹了vue項(xiàng)目打包后瀏覽器緩存問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03vue中對(duì)虛擬dom的理解知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家整理了一篇關(guān)于vue中對(duì)虛擬dom的理解知識(shí)點(diǎn)總結(jié)內(nèi)容,有興趣的朋友們可以學(xué)習(xí)參考下。2021-06-06vue項(xiàng)目中使用require.context引入組件
本文主要介紹了vue項(xiàng)目中使用require.context引入組件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08Vue3?echarts組件化及使用hook進(jìn)行resize方式
這篇文章主要介紹了Vue3?echarts組件化及使用hook進(jìn)行resize方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04