美文网首页Vuevuevue专题
用vue来写一个新项目,建好脚手架之后<-->开发之前的准备动作

用vue来写一个新项目,建好脚手架之后<-->开发之前的准备动作

作者: 风中凌乱的男子 | 来源:发表于2019-08-21 23:09 被阅读0次

    前言:

    拿到一个新项目,着手开发之前,我习惯先把准备工作准备充分,至于什么准备工作,我写的是移动端,首当其冲的就是设置rem单位转换(ps:我习惯用rem)直接看我这两篇文章
    < px2rem-loader(Vue:将px转化为rem,适配移动端)>
    < vue移动端中使用lib-flexible和px2rem,再引入第三方UI库导致第三方UI库的样式也变小的问题 >
    我一般直接引入第二篇文章中的插件,插件配置完成后在App.vue中加上这段代码。
    才会动态变化布局大小样式。

    document.addEventListener("DOMContentLoaded", setFontSize);
    window.addEventListener("resize", setFontSize);
    function setFontSize() {
      const html = document.querySelector("html");
      let fontSize = window.innerWidth / 10;
      fontSize = fontSize > 65 ? 65 : fontSize;
      html.style.fontSize = fontSize + "px";
    }
    

    第二个,既然是移动端,index.htmlmeta标签一定要加,上代码

    <meta name="viewport" content="width=device-width,minimum- scale=1.0,maximum-scale=1.0,user-scalable=no" />
    

    第三个,安装所需要的插件依赖,比如axios,vuex,vue-wechat-title,vue-totop,element-ui,vant等等,看自己所需,vue-wechat-title是改变路由页面title的插件,vue-totop是返回顶部的插件。安装命令如下:

    cnpm install axios --save 
    cnpm install vuex --save 
    cnpm install vue-wechat-title --save 
    cnpm install vue-totop --save 
    cnpm install element-ui --save 
    cnpm install vant --save 
    

    第四个,既然安装了依赖接下来就是配置依赖了。一个一个说,没有提到的可以大家可以百度下。

    先说 `vue-wechat-title`
    上面已经安装好了,直接在`main.js`内引用
    //改变页面的title插件
    import VueWechatTitle from 'vue-wechat-title'
    Vue.use(VueWechatTitle)
    使用的话就在`router`文件夹的`index.js`中这样使用
    //index.js
    import Vue from 'vue'
    import Router from 'vue-router'
    Vue.use(Router)
    const router = new Router({
      routes: [
        {
          path: "/",
          redirect: "/index"
        },//重定向
        {
          path: "/index",
          component: () => import('../pages/index.vue'),
          meta: {
            showFooter: true, //这个是控制底部导航菜单显示不显示,用法很简单,
                              //直接在底部导航菜单组件上这样使用就行了
                              //<!--底部导航开始-->
                             // <tabBar v-show="$route.meta.showFooter"></tabBar>
                             // <!--底部导航结束-->
            title:"医佰康云课堂" //在这里使用
          }
        },
      ]
    })
    export default router;
    
    然后在App.vue中 
    <router-view  v-wechat-title='$route.meta.title'></router-view>
    这样就实现了路由页面的title属性动态变化。
    
    再说`vue-totop`
    也是在`main.js中全局引用`
    //返回顶部插件
    import vueToTop from 'vue-totop'
    Vue.use(vueToTop)
    然后在需要的页面中就可以这样用了
    <!-- 返回顶部插件 -->
    <div class="toTop" @click="show"> //show方法下面会提到
       <vueToTop
         :type="config.type"
         :top="config.top"
         :right="config.right"
         :size="config.size"
         color="#5dd6c7"
         bottom="250"
         :duration="config.duration"
        ></vueToTop>
    </div>
    export default {
            name: "Index",
            inject: ["reload"],//这个是无感刷新当前页面的方法,下面会讲到
            data() {
              return {
                value: "",
                config: {
                  type: 4,
                  right: "0",
                  top: "200",
                  size: "40",
                  duration: "1" //这里返回顶部速度为1毫秒,是为了解决ios手机返回顶部后立即下滑出现的抖动闪烁现象。
                }
            };
        },
     }
    具体用法建议大家参考这个教程
    [https://github.com/1006008051/vue-totop](https://github.com/1006008051/vue-totop)
    ----------------------------------------------------------------------------------------
    下面说一说 `inject: ["reload"]`,//这个无感刷新当前页面的方法的用法
    ----------------------------------------------------------------------------------------
    在需要的.vue组件文件中,像上面一样那样写好,注意是和data同级。
    使用之前在`App.vue`中,和`data`同级,这样写:
    //无感刷新当前页面
      provide() {
        return {
          reload: this.reload
        };
      },
    `data`中这样写:
    data() {
        return {
          isRouterAlive: true
        };
      },
    `methods`中这样写:
    //无感刷新当前页面
    reload() {
       this.isRouterAlive = false;
       this.$nextTick(function() {
         this.isRouterAlive = true;
       });
    },
    `router-view`改写成这样:
    <router-view class="Router" v-if="isRouterAlive" v-wechat-title='$route.meta.title'></router-view>
    
    无感刷新当前页面的方法配置完了,在需要的.vue组件文件中,这样写:
    //注意是和data同级。
    inject: ["reload"],
    data:{
        return{
          .....
        }
    }
    然后在需要调用的方法中这样写:
    methods: {
        //show方法是上面提到的为了解决ios设备上的那个bug
          因为没有很好的办法可以解决,如果大家解决了,麻烦告诉下小弟,感激不尽~
        show() { 
          setTimeout(() => {
            this.reload(); //这样调用就行了
          }, 2);
        }
     }
    ----------------------------------------------------------------------------------------
    

    移动端交互路由跳转加上左滑动右滑动的效果我觉得挺好的,具体实现,代码这样写:

    1. 在main.js中这样写:
        //监测页面的进退,实现动画效果
        window.addEventListener('popstate', function (e) {
        router.isBack = true
        }, false)
    2. 在App.vue中这样写:
        watch: {
          $route(to, from) {
          // 切换动画
          let isBack = this.$router.isBack; // 监听路由变化时的状态为前进还是后退
          if (isBack) {
            this.transitionName = "slide-left";
          } else {
            this.transitionName = "slide-right";
          }
            this.$router.isBack = false;
          }
      },
    data中加上这个:
    data() {
        return {
          transitionName: "slide-right", //初始过渡动画方向
        };
      },
    router-view 改成这样:
        <transition :name="transitionName">
            <router-view class="Router" v-if="isRouterAlive" v-wechat-title='$route.meta.title'></router-view>
        </transition>
    css样式这样写:
    <style>
        body,
        html,
        #app {
          width: 100%;
        }
        #app {
          overflow-x: hidden;
        }
        .Router {
          position: absolute;
          height: 100%;
          transition: all 0.377s ease;
          will-change: opacity;
          top: 0;
          backface-visibility: hidden;
          /* perspective: 1000; */  /* 这里如果打开的话就会引起fiexd固定定位失效,不要打开 */ 
        }
        .slide-left-enter,
        .slide-right-leave-active {
          opacity: 0;
          transform: translate3d(-100%, 0, 0);
        }
    
        .slide-left-leave-active,
        .slide-right-enter {
          opacity: 0;
          transform: translate3d(100%, 0, 0);
        }
    </style>
    --------------------------------------------------------------------
    

    接下来说说element-ui和vant-ui的按需加载引入

    前面已经安装过element-ui和vant,想要按需加载他们, 就要安装两个插件
    cnpm install babel-plugin-component -D
    cnpm install babel-plugin-import -D
    安装完毕后,在.babelrc中这样配置:
    {
      "presets": [
        [
          "env",
          {
            "modules": false,
            "targets": {
              "browsers": [
                "> 1%",
                "last 2 versions",
                "not ie <= 8"
              ]
            }
          }
        ],
        "stage-2"
      ],
      "plugins": [
        "transform-vue-jsx",
        "transform-runtime",
        [
          "import",
          {
            "libraryName": "vant",
            "libraryDirectory": "es",
            "style": true
          }
        ],
        [
          "component",
          {
            "libraryName": "element-ui",
            "styleLibraryName": "theme-chalk"
          }
        ]
      ]
    }
    
    在`src`目录下新建两个文件夹`element`和`vant`
    文件夹内新建俩`index.js`文件分别这样写:
    `element` > `index.js`
    // 导入自己需要的组件
    import { Select, Option, OptionGroup, Input, Tree, Dialog, Row, Col, Button, Message ,Loading} from 'element-ui'
    const element = {
        install: function (Vue) {
            Vue.use(Select)
            Vue.use(Option)
            Vue.use(OptionGroup)
            Vue.use(Input)
            Vue.use(Tree)
            Vue.use(Dialog)
            Vue.use(Row)
            Vue.use(Col)
            Vue.use(Button),
            Vue.prototype.$loading = Loading.service
            Vue.prototype.$message = Message
        }
    }
    export default element
    
    `vant` > `index.js`
    
    // 导入自己需要的组件
    import { Button, Search, Icon, Swipe, SwipeItem, Lazyload, Row, Col, Image ,Divider,NoticeBar,Dialog,Tab, Tabs,Pagination } from 'vant';
    const vant = {
        install: function (Vue) {
            Vue.use(Button)
            Vue.use(Search)
            Vue.use(Icon)
            Vue.use(Swipe)
            Vue.use(SwipeItem)
            Vue.use(Lazyload)
            Vue.use(Row)
            Vue.use(Col)
            Vue.use(Image);
            Vue.use(Divider);
            Vue.use(NoticeBar);
            Vue.use(Dialog);
            Vue.use(Pagination);
            Vue.use(Tab).use(Tabs);
        }
    }
    export default vant;
    
    然后在main.js中这样引入
    import vant from './vant/index'
    Vue.use(vant)
    // css样式还是需要全部引入
    import 'element-ui/lib/theme-chalk/index.css'
    import element from './element/index'
    Vue.use(element)
    这样就打包后就是按需加载的了。
    
    

    下面就是封装ajax,重头戏来了。用到了axios,作为请求工具。

    在  `src`目录下新建api文件夹,内新建ajax.js,和 index.js,里面的代码如下
    /* ajax.js */
    /*
    ajax 请求函数模块
    */
    
    import { showLoading, hideLoading } from '../assets/js/loading';
    //Loading加载,需要的loading.js文件写在下面
    import axios from 'axios'
    /**
     * 向外部暴漏一个函数 ajax
     * @param {*} url 请求路径,默认为空
     * @param {*} data 请求参数,默认为空对象
     * @param {*} type 请求方法,默认为GET
     */
    export default function ajax(url = '', data = {}, type = 'GET') {
        // 返回值 Promise对象 (异步返回的数据是response.data,而不是response)
        return new Promise(function (resolve, reject) {
            // (利用axios)异步执行ajax请求
            let promise // 这个内部的promise用来保存axios的返回值(promise对象)
            if (type === 'GET') {
                // 准备 url query 参数数据
                let dataStr = '' // 数据拼接字符串,将data连接到url
                Object.keys(data).forEach(key => {
                    dataStr += key + '=' + data[key] + '&'
                })
                if (dataStr !== '') {
                    dataStr = dataStr.substring(0, dataStr.lastIndexOf('&'))
                    url = url + '?' + dataStr
                }
                // 发送 get 请求
                promise = axios.get(url)
            } else {
                // 发送 post 请求
                promise = axios.post(url, data)
            }
            promise.then(response => {
                // 成功回调resolve()
                resolve(response.data)
            })
                .catch(error => {
                    // 失败回调reject()
                    reject(error)
                })
        })
    }
    
    /* 请求拦截器(请求之前的操作) */
    axios.interceptors.request.use((req) => {
        showLoading();
        return req;
    }, err => Promise.reject(err));
    
    /* 请求之后的操作 */
    axios.interceptors.response.use((res) => {
        hideLoading();
        return res;
    }, (err) => {
        hideLoading();
        return Promise.reject(err);
    });
    /* loading.js */
    import { Loading } from 'element-ui';
    
    let loadingCount = 0;
    let loading;
    
    const startLoading = () => {
        loading = Loading.service({
            lock: true,
            text: '加载中……',
            background: 'rgba(0, 0, 0, 0.7)'
        });
    };
    
    const endLoading = () => {
        loading.close();
    };
    
    export const showLoading = () => {
        if (loadingCount === 0) {
            startLoading();
            console.log(loadingCount)
        }
        loadingCount += 1;
        console.log(loadingCount)
    
    };
    
    export const hideLoading = () => {
        if (loadingCount <= 0) {
            return;
        }
        loadingCount -= 1;
        if (loadingCount === 0) {
            endLoading();
        }
    };
    /* index.js ,这里封装后端接口*/
    /*
    与后台交互模块 (依赖已封装的ajax函数)
     */
    import ajax from './ajax'
    const BASE_URL = 'https://ky.xxxxxx.com'
    // const BASE_URL = '/api'
    /**
     * 获取首页数据信息
     */
    export const reqHomePageData = mod_id => ajax(`${BASE_URL}/api/5d5a1d39efef1`, { mod_id }, 'POST'); //首页数据接口
    /**
     * 获取热门搜索数据接口
     */
    export const reqHotSearch = () => ajax(`${BASE_URL}/api/5d5b87de18afa`, {}, 'POST');
    /**
     * 发送请求查询证书信息
     */
    export const reqBook = content => ajax(`${BASE_URL}/api/5d4cd3e8d80f9`, { content }, 'POST'); 
    /**
     * 发送请求查询导师列表
     */
    export const reqTeacherList = page => ajax(`${BASE_URL}/api/5d5bd91cb748c`, { page }, 'POST'); 
    
    
    

    接下来配置vuex

    1. 在`src`目录下新建一个文件夹store,在该文件夹内新建
        `index.js`
        `state.js`
        `mutation-types.js`
        `mutations.js`
        `getters.js`
        `actions.js`
        文件
        //index.js内的代码如下:
        /*
    vuex最核心的管理对象store
    组装模块并导出 store 的地方
     */
    // 首先引入Vue及Vuex
    import Vue from 'vue'
    import Vuex from 'vuex'
    // 引入四个基本模块
    import state from './state'
    import mutations from './mutations'
    import actions from './actions'
    import getters from './getters'
    // 一定要声明使用插件
    Vue.use(Vuex)
    // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
    export default new Vuex.Store({
        state,
        mutations,
        actions,
        getters
    })
    /*state.js*/
    /*
    State:状态对象
     */
    export default {
        mod_id: '1313',
        swiper: {}, // 轮播图数据
    }
    
    /*mutation-types.js*/
    /*
    包含n个mutation的type名称常量
     */
    export const GET_SWIPER = 'get_swiper' // 接收轮播图数据
    
    /*mutations.js*/
    import { GET_SWIPER } from './mutation-types'
    // [方法名](state,{param}){}
    export default {
        [GET_SWIPER](state, { swiper }) {
            state.swiper = swiper
        },
    }
    /*actions.js*/
    /*
    Action:通过操作mutation间接更新state的多个方法的对象
     */
    
    import {
        GET_SWIPER
    } from './mutation-types'
    import {
        reqHomePageData
    } from '../api'
    export default {
        // 异步获取首页数据
        async getHomePageData({ commit, state }) {
            // 从state状态中获取到mod_id用来设置reqHomePageData的参数
            const mod_id = state.mod_id
            // 1. 发送异步ajax请求
            const result = await reqHomePageData(mod_id)
            // 2. 提交一个mutation,获取到轮播图数据
            // console.log(result)
            const swiper = result[2]
            commit(GET_SWIPER, { swiper })
    }
    /*getters.js*/
    暂时没有东西
    ——————————————————————————————————
    vuex中的数据要根据自己的实际情况来写
    下面我总结了一点流程,希望对你有所帮助。
    ——————————————————————————————————
    封装接口请求操作步骤
    1. 在api.js中新增接口
           export const reqHotSearch = () => ajax(`${BASE_URL}/api/5d5b87de18afa`);  //这是get请求的写法
           export const reqHomePageData = mod_id => ajax(`${BASE_URL}/api/5d5a1d39efef1`, { mod_id }, 'POST’);//这是post请求的写法
    2. 在state.js中新增一个状态对象容器
           hotSearch:{  } //热门搜索数据
    3. 在mutation-types.js中新增常量
           export const GET_HOTSEARCH = 'get_hotSearch' // 接收热门搜索数据
    4. 在mutations.js中引入第三步的常量
        import { GET_HOTSEARCH } from './mutation-types'
        暴露一个方法
        [GET_HOTSEARCH](state, { hotSearch }) {
            state.hotSearch = hotSearch
            },
    5. 在actions.js中引入第三步的常量和第一步的接口
        import { GET_HOTSEARCH } from './mutation-types'
        import { reqHotSearch } from '../api'
        然后在异步发起请求——-post传参的写法,固定的参数在state中提前定义好
        // 异步获取首页数据
            async getHomePageData({ commit, state }) {
            // 从state状态中获取到mod_id用来设置reqHomePageData的参数
            const mod_id = state.mod_id //这里获取参数
            // 1. 发送异步ajax请求
            const result = await reqHomePageData(mod_id)
            // 2. 提交一个mutation,获取到轮播图数据
            // console.log(result)
            const swiper = result[2]
            commit(GET_SWIPER, { swiper })
        }
        // 异步获取食品分类列表
            async getHotSearch({ commit }) {
            // 发送异步ajax请求
            const result = await reqHotSearch()
            // 提交一个mutation
            if (result.code === 0) {
                const hotSearch = result.data
                commit(GET_HOTSEARCH, { hotSearch })
            }
        },
    传参数的请求,在需要发送请求的页面这样写:
    在methods中:
    async query() {
          if (this.number == "") {   
            this.$message.error("请输入证书编号");
          } else {
            //异步获取证书信息
            const result = await reqBook(this.number);
            console.log(result)
          }
        },
      },
    点击调用,或者在mounted中自动调用根据需求来做。
    this.query();
    调用actions.js中的方法和取vuex中的数据这样写:
    
    调用:
    引入 import { mapActions, mapState } from "vuex";
    在methods中:
     ...mapActions(["getHotSearch"])
    然后点击调用this.getHotSearch(),或者在mounted中自动调用根据需求来做。
    取数据:
    computed: {
        ...mapState(["hotSearch"])
    }
    这样hotSearch内就取到了数据。
    

    至此,前期准备工作就做好了,就可以着手进行开发了。
    祝愉快~

    相关文章

      网友评论

        本文标题:用vue来写一个新项目,建好脚手架之后<-->开发之前的准备动作

        本文链接:https://www.haomeiwen.com/subject/wzgvsctx.html