zoukankan      html  css  js  c++  java
  • vue相关

    vue路由主动态引入

    1.将子路由分模块封装

     例如  home.router.js

    export default {
        path: '/',
        name: 'Home',
        component: () => import('../../views/Home.vue')
    }

    2. 主路由配置

    mport Vue from 'vue'
    import VueRouter from 'vue-router'
    Vue.use(VueRouter)
    
    //路由主动态引入
    const routerList = [];
    
    function importALL(r) {
      r.keys().forEach((key) => routerList.push(r(key).default));
    }
    
    //webpack 查找文件(代替所有import)
    //1.文件路径
    //2.是否子文件夹
    //3.匹配规则
    importALL(require.context('./', true, /.router.js/));
    
    const routes = [
      ...routerList,
    ]
    
    const router = new VueRouter({
      mode: 'history',
      base: process.env.BASE_URL,
      routes
    })
    
    export default router

    vue配置跨域

    1.当前项目的根路径下新建一个文件,文件名是固定的 vue.config.js

      

     2.vue.config.js配置

    module.exports = {
        devServer: {
            compress: false, //配置是否启用 gzip 压缩。所有来自 dist/ 目录的文件都做 gzip 压缩和提供为服务
            // open: true,
            // host: 'localhost',
            // port: 8080,
            // https: false,
            proxy: { //配置跨域
                '/api': {
                    target: 'https://api-xxxxxxx', //后台接口
                    ws: true,
                    changOrigin: true, //允许跨域
                    pathRewrite: {
                        '^/api': '' //请求的时候使用这个api就可以
                    }
                }
            }
        }
    }

      

    axios,主文件设置

    const service = axios.create({
        baseURL: '/api',
    })

    请求示例:

    //gettRequest为封装的请求方法 , 与解决跨域问题无关

    gettRequest("/goods/detail", { goods_id: 55345 }).then((res) => { console.log(res); });

    vue路由权限控制

    1.配置路由元对象 , 是否需要权限才能进入

    {
        path: '/goods',
        name: 'goods',
        component: () => import('../../views/Goods.vue'),
        meta: {
            requierAuth: true //需要权限才能进入
        }
    }

    2.main文件配置全局路由守卫

    main.js代码

    import Vue from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    
    Vue.config.productionTip = false;
    
    //以token为例
    router.beforeEach((to, from, next) => {
      let token = sessionStorage.getItem('token');
    
      //需要验证之后才能进入
      if (to.meta.requierAuth) {
        if (token) {
          next();
        } else {
          console.log(to.fullPath)
          next({
            path: './login',
            query: {
              redirect: to.fullPath // 将跳转的路由path作为参数,登录成功后跳转到该路由
            }
          })
        }
      } else {
        next()
      }
    })
    
    
    new Vue({
      router,
      store,
      render: h => h(App)
    }).$mount('#app')

    2.登录页 ,登录后获取token , 跳回上一路由

    <template>
      <div class="page">
        <h1>login</h1>
        <button @click="loginClick">点我登录</button>
      </div>
    </template>
    
    <script>
    export default {
      name: "",
      components: {},
      data() {
        return {};
      },
      methods: {
        loginClick() {
          sessionStorage.setItem("token", 123);
          let redirect = this.$route.query.redirect;
          this.$router.push(redirect); //.catch(() => {});
        },
      },
    };
    </script>
    

    axios api层架构封装

    1.目录结构

    2. service.js文件    统一处理接口 , 拦截 , 状态处理

    import axios from 'axios';
    //从本地获取token
    //token=>令牌 64 128 256 随机字符串 + 用户名 + 用户密码 + 当前时间 + ......
    function getTokenByLocal() {
        let token = sessionStorage.getItem('token') || '';
        return token;
    }
    
    //创建axios实例
    const service = axios.create({
        baseURL: '/api',
        timeout: 5000,
        // headers: {'X-Custom-Header': 'foobar'}
    })
    // 在实例已创建后修改默认值
    // service.defaults.headers.common['Authorization'] = 'AUTH_TOKEN';
    service.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
    
    //请求拦截
    service.interceptors.request.use(
        config => {
            if (getTokenByLocal()) {
                config.headers['Authorization'] = getTokenByLocal()
            }
            return config;
        },
        error => {
            return Promise.reject(error);
        }
    )
    
    //响应拦截
    service.interceptors.response.use(
        response => {
            let res = response.data;
            if (res.code == "401") { //根据返回值 状态码进行不同操作
                location.href = "/login"
            }
            return Promise.resolve(res)
        },
        error => {
            return Promise.reject(error)
        }
    )
    
    export default service;

    3.common.js   传参处理

    import service from './service';
    //post请求 80% 耦合度极低=> 复用性极高
    //细分解耦
    export function requestOfPost(url, data) {
        return service.post(url, data)
    }
    export function requestOfGet(url, data) {
        return service.get(url, {
            params: data
        })
    }

    4.api.js   返回值处理

    import {
        requestOfPost,
        requestOfGet
    } from './common'
    export function postRequest(url, data) {
        return new Promise((resolve, reject) => {
            requestOfPost(url, data).then(res => {
                resolve(res)
            }).catch(error => reject(error))
        })
    }
    
    export function gettRequest(url, data) {
        return new Promise((resolve, reject) => {
            requestOfGet(url, data).then(res => {
                resolve(res)
            }).catch(error => reject(error))
        })
    }

    引入使用

    import { gettRequest } from "../request/api";
    export default {
      name: "",
      components: { Login },
      created() {
        gettRequest("/goods/detail", { goods_id: 55345 }).then((res) => {
          console.log(res);
        });
      },
      data() {
        return {};
      },
    };

     vue引入Fastclick 插件解决 移动端300ms延迟

     1.安装

    yarn add fastclick --save

    2. 在main.js中 导入

    import Fastclick from "fastclick"

    3.在main.js中  调用

    Fastclick.attach(document.body);

    4.可能出现的问题 : 多词点击报错

    解决方案

    * {
      /*避免点击过快 fastclick 报错*/
      touch-action: pan-y;
    }

    vue懒加载

    1.安装vue-lazyload

    yarn add vue-lazyload --save

    2.在main.js中 导入

    import VueLazyLoad from "vue-lazyload"

    3.安装配置懒加载插件

    Vue.use(VueLazyLoad, {
      loading: require("./assets/img/common/placeholder.png")
    });

    4.使用

    :src换为 v-lazy
    <img v-lazy="goodsItem.goods_small_logo" alt="" />

    vue 单位转换

    转换vw

      1.安装postcss-px-to-viewport

      

    yarn add postcss-px-to-viewport --save--dev

      2.package.json 同级文件下 ,新建postcss.config.js文件

    module.exports = {
        plugins: {
            autoprefixer: {},
            "postcss-px-to-viewport": {
                viewportWidth: 375, // 视窗的宽度,对应的是我们设计稿的宽度.
                viewportHeight: 667, // 视窗的高度,对应的是我们设计稿的高度.(也可以不配置)
                unitPrecision: 5, // 指定`px`转换为视窗单位值的小数位数(很多时候无法整除)
                viewportUnit: 'vw', // 指定需要转换成的视窗单位,建议使用vw
                selectorBlackList: ['ignore', 'tab-bar'], // 指定不需要转换的类,后面再讲.
                minPixelValue: 1, // 小于或等于`1px`不转换为视窗单位.
                mediaQuery: false, // 允许在媒体查询中转换`px`
                exclude: [/^TabBar/]
            },
        }
    }

    自定义vue 插件

    举例 :

    toast/toast.vue
    <template>
      <div class="toast" v-show="isShow">
        {{ message }}
      </div>
    </template>
    
    <script>
    export default {
      name: "Toast",
      components: {},
      data() {
        return {
          isShow: false,
          message: "",
        };
      },
      methods: {
        show(message = "空内容", duration = 2000) {
          this.isShow = true;
          this.message = message;
          console.log(123);
          if (timer) {
            clearTimeout(timer);
          }
          let timer = setTimeout(() => {
            this.isShow = false;
            this.message = "";
            clearTimeout(timer);
          }, duration);
        },
      },
    };
    </script>
    
    <style scoped>
    .toast {
      padding: 8px 10px;
      background: rgba(0, 0, 0, 0.75);
      position: fixed;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      color: #fff;
      z-index: 999;
      font-size: 24px;
    }
    </style>

    toast/index.js

      toast/index.js方案一:

     

    import Toast from "./Toast";
    const obj = {};
    obj.install = function (Vue) {
        // 1.构建组件构造器
        const ToastCompon = Vue.extend(Toast);
        //2.new的方式 创建组件对象
        const toast = new ToastCompon();
        //3.将组件对象挂载到某一个对象上
        toast.$mount(document.createElement('div'));
        //4.将toast.$el添加到body中
        document.body.appendChild(toast.$el)
        Vue.prototype.$toast = toast;
    }
    export default obj;

      toast/index.js方案二:

    import Toast from './Toast';
    let obj = {};
    obj.install = function (Vue) {
        Vue.component(Toast.name,Toast);
    }
    export default obj;

    main.js

    import Toast from "components/common/toast/index"
    ...
    Vue.use(Toast);

    使用

    this.$toast.show(res, 1500);

    vue 封装滚动插件  better-scroll

    版本1.15.2

    封装  better-scroll

    Scroll.vue

    <template>
      <div class="wrapper" ref="wrapper">
        <div class="content">
          <slot></slot>
        </div>
      </div>
    </template>
    
    <script>
    //scroll组件必须要设定高度
    import BScroll from "better-scroll";
    export default {
      name: "Scroll",
      props: {
        probeType: {
          type: Number,
          default() {
            return 0;
          },
        },
        pullUpLoad: {
          type: Boolean,
          default() {
            return false;
          },
        },
      },
      components: {},
      data() {
        return {
          scroll: null,
        };
      },
      mounted() {
        this.scroll = new BScroll(this.$refs.wrapper, {
          click: true,
          probeType: this.probeType,
          pullUpLoad: this.pullUpLoad,
          //  pullUpLoad: {
          // threshold: -30 // 当上拉距离超过30px时触发 pullingUp 事件
          //stop: 20 // 回弹停留在距离顶部20px的位置
          // },
          // observeDOM: true,
          // observeImage: true,
        });
        //监听滚动
        this.scroll.on("scroll", (position) => {
          this.$emit("scroll", position);
        });
        //监听上拉加载
        this.scroll.on("pullingUp", () => {
          this.$emit("loadMore", "上啦加载更多");
        });
      },
      methods: {
        scrollTo(x, y, timer = 300) { //滚动到指定位置
          this.scroll && this.scroll.scrollTo(x, y, timer);
        },
        finishPullUp() {
          //事情做完,需要调用此方法告诉 better-scroll 数据已加载,否则上拉事件只会执行一次
          this.scroll && this.scroll.finishPullUp();
        },
        refresh() {
          //刷新
          this.scroll && this.scroll.refresh();
        },
        getScrollY() {
          //获取滚动Y轴位置
          return this.scroll ? this.scroll.y : 0;
        },
      },
    };
    </script>
    
    <style scoped></style>

    如何使用及注意事项

    以下举例都是通过 this.$refs.scroll 来调用组件中的方法

    1.引入scroll  组件将需要滚动的内容 包裹  ,  scroll组件必须要有高度 , 并设置overflow:hidden

    2.每次下拉加载更多 , 需要  调用 this.$refs.scroll.finishPullUp();

    3.滚动到指定元素位置  this.$refs.scroll.scroll.scrollToElement(this.$refs.tabControl2.$el, 200);

    4.滚动到指定位置  this.$refs.scroll.scrollTo(x, y);

    5.被包裹的内容的宽高发生改变 , 则需要重新调用   this.$refs.scroll.refresh();

    例如图片加载完成后 ,高度发生变化 ,执行this.$refs.scroll.refresh() 

    item.vue
    //item.vue
    <img v-lazy="goodsItem.goods_small_logo" alt="" @load="imageLoad" />
      methods: {
        imageLoad() {
          this.$bus.$emit("ItemImageLoad");
        },
     }

      home.vue

    data() {
            return {
                itemImgListener: null,
                refresh: null
            }
    },
    mounted() {
        this.refresh = debounce(this.$refs.scroll.refresh, 200); //debounce为防抖函数
      this.itemImgListener = () => { this.refresh(); }; 
      this.$bus.$on("ItemImageLoad", this.itemImgListener); }
    }  



    6.跳转路由 , 保留页面位置

    因为使用了 keep-alive 进行页面缓存 , 所以调用以下两个函数

    activated() {
        //创建时跳到获取保留的位置,并刷新下页面
        this.$refs.scroll.scrollTo(0, this.saveY, 1);
        this.$refs.scroll.refresh();
      },
      deactivated() {
        //离开时保留滚动位置
        this.saveY = this.$refs.scroll.getScrollY();
        this.$bus.$off("itemImageLoad", this.itemImageListener); //解绑itemImageLoad
      },

    简单举例:   

    <template>
      <div id="home">
        <scroll
          class="content"
          ref="scroll"
          @scroll="contentScrollTop"
          :probeType="3"
          :pullUpLoad="true"
          @loadMore="loadMore"
        >
         ...需要滚动的内容
        </scroll>
    </div> </template> <script>

      import Scroll from "components/common/scroll/Scroll.vue";
    export default {
      name: "Home",
      components: {
        Scroll,
      },
      props: {},
      data() {
        return {     
        };
      },
      created() {
       
      },
      methods: {
        getHomeGoods(type, numpage) {
          const page = this.goods[type + ""].page + 1;
          getHomeGoods(type, page, 10).then((res) => { //滚动加载更多
            this.goods[type + ""].list.push(...res.message.goods);
            this.goods[type + ""].page += 1;
            //下拉加载更多
            this.$refs.scroll.finishPullUp();
          });
        },
        tabClick(index) {//滚动到元素位置
          this.$refs.scroll.scroll.scrollToElement(this.$refs.tabControl2.$el, 200);
        },
        backClick() {
          //返回顶部
          this.$refs.scroll.scrollTo(0, 0);
        },
        debounce(func, delay) {
        //防抖
          let timer = null;
          return function (...args) {
              if (timer) {
                  clearTimeout(timer);
              }
            timer = setTimeout(() => {
                func.apply(this, args);
            }, delay);
          }
    
      },
      computed: {
      
      },
      mounted() {
        this.refresh = debounce(this.$refs.scroll.refresh, 200);
            this.itemImgListener = () => {
                this.refresh();
            };
            this.$bus.$on("ItemImageLoad", this.itemImgListener);
      },
      activated() {
        //创建时跳到获取保留的位置,并刷新下页面
        this.$refs.scroll.scrollTo(0, this.saveY, 1);
        this.$refs.scroll.refresh();
      },
      deactivated() {
        //离开时保留滚动位置
        this.saveY = this.$refs.scroll.getScrollY();
        this.$bus.$off("itemImageLoad", this.itemImageListener);
      },
    };
    </script>
    
    <style scoped>
    .content {
      /**scroll组件必须要设定高度 */
      /* height: calc(100vh - 93px); */
      overflow: hidden;
      position: fixed;
      top: 44px;
      bottom: 49px;
      z-index: 10;
      left: 0;
      right: 0;
      overflow: hidden;
    }
    </style>

    ...

  • 相关阅读:
    [转]system函数返回值探究
    [转]bat中的特殊字符,以及需要在bat中当做字符如何处理
    [转]null和""以及==与equals的区别
    粘包问题
    并发编程
    GIL锁
    五种IO模型
    css选择器
    并发与串行
    模块(二)
  • 原文地址:https://www.cnblogs.com/wxyblog/p/14602530.html
Copyright © 2011-2022 走看看