国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

vue2.0 項目開發小結

yagami / 3687人閱讀

摘要:項目架構項目目錄項目目錄是采用自動生成,其它按需自己新建就好了。

項目架構 項目目錄
├── build
├── config
├── dist
│?? └── static
│??     ├── css
│??     ├── fonts
│??     ├── images
│??     ├── js
│??     └── lib
├── src
│?? ├── api
│?? ├── assets
│?? │?? ├── global
│?? │?? └── images
│?? │??     └── footer
│?? ├── components
│?? │?? ├── common
│?? │?? ├── news
│?? │?? └── profile
│?? │??     └── charge
│?? ├── config
│?? ├── mixin
│?? ├── router
│?? ├── service
│?? ├── store
│?? └── util
└── static
    ├── images
    └── lib 

項目目錄是采用 vue-cli 自動生成,其它按需自己新建就好了。

開發實踐 動態修改 document title

在不同的路由頁面,我們需要動態的修改文檔標題,可以將每個頁面的標題配置在路由元信息 meta 里面帶上,然后在 router.afterEach 鉤子函數中修改:

import Vue from "vue";
import Router from "vue-router";

Vue.use(Router);
const router = new Router({
  mode: "history",
  routes: [
    { path: "/", component: Index, meta: { title: "推薦產品得豐厚獎金" } },
    {
      path: "/news",
      component: News,
      meta: { title: "公告列表" },
      children: [
        { path: "", redirect: "list" },
        { path: "list", component: NewsList },
        { path: "detail/:newsId", component: NewsDetail, meta: { title: "公告詳情" } }
      ]
    },
    {
      path: "/guide",
      component: GuideProtocol,
      meta: {
        title: "新手指南"
      }
    }
  ]
});

// 使用 afterEach 鉤子函數,保證路由已經跳轉成功之后修改 title
router.afterEach((route) => {
  let documentTitle = "xxx商城會員平臺";
  route.matched.forEach((path) => {
    if (path.meta.title) {
      documentTitle += ` - ${path.meta.title}`;
    }
  });

  document.title = documentTitle;
});
根據 URL 的變化,動態更新數據

通常在一個列表集合頁,我們需要做分頁操作,同時分頁數據需要體現在 URL 中,那么如何動態的根據 URL 的變動來動態的獲取數據呢,我們可以使用 watch API,在 watch 里面監聽 $route,同時使用 this.$router.replace API 來改變 URL 的值。下面是示例代碼 common.js

import qs from "qs";

export default {
  data() {
    return {
      queryParams: {
        currentPage: 1,
        pageSize: 10
      }
    };
  },
  methods: {
    handlePageNoChange(e) {
      this.queryParams.currentPage = e;
      this.replaceRouter();
    },

    replaceRouter() {
      const query = qs.stringify(this.queryParams);
      this.$router.replace(`${location.pathname}?${query}`);
    },

    routeChange() {
      this.assignParams();
      this.fetchData();
    },

    assignParams() {
      this.queryParams = Object.assign({}, this.queryParams, this.$route.query);
    }
  },
  mounted() {
    this.assignParams();
    this.fetchData();
  },
  watch: {
    $route: "routeChange"
  }
};

我們將這部分代碼抽取到一個公共的 mixin 中,在需要的組件那里引入它,同時實現自定義的同名 fetchData() 方法
mixin API 文檔:https://cn.vuejs.org/v2/guide...

export default DemoComponent {
  mixins: [common],
  data() {
    return {
      // 組件內部自定義同名查詢參數,將會和 mixin 中的默認參數合并
      queryParams: {
        categoryId: "",
        pageSize: 12
      },
    }
  },
  methods: {
    fetchData() {
       // 發送請求
    }
  }
}
Event Bus 使用場景

我們在項目中引入了 vuex ,通常情況下是不需要使用 event bus 的,但是有一種情況下我們需要使用它,那就是在路由鉤子函數內部的時,在項目中,我們需要在 beforeEnter 路由鉤子里面對外拋出事件,在這個鉤子函數中我們無法去到 this 對象。

beforeEnter: (to, from, next) => {
    const userInfo = localStorage.getItem(userFlag);
    if (isPrivateMode()) {
        EventBus.$emit("get-localdata-error");
        next(false);
        return;
    }
})

App.vuemouted 方法中監聽這個事件

EventBus.$on("get-localdata-error", () => {
    this.$alert("請勿使用無痕模式瀏覽");
});
自定義指令實現埋點數據統計

在項目中通常需要做數據埋點,這個時候,使用自定義指令將會變非常簡單

在項目入口文件 main.js 中配置我們的自定義指令

// 坑位埋點指令
Vue.directive("stat", {
  bind(el, binding) {
    el.addEventListener("click", () => {
      const data = binding.value;
      let prefix = "store";
      if (OS.isAndroid || OS.isPhone) {
        prefix = "mall";
      }
      analytics.request({
        ty: `${prefix}_${data.type}`,
        dc: data.desc || ""
      }, "n");
    }, false);
  }
});
使用路由攔截統計頁面級別的 PV

由于第一次在單頁應用中嘗試數據埋點,在項目上線一個星期之后,數據統計后臺發現,首頁的 PV 遠遠高于其它頁面,數據很不正常。后來跟數據后臺的人溝通詢問他們的埋點統計原理之后,才發現其中的問題所在。

傳統應用,一般都在頁面加載的時候,會有一個異步的 js 加載,就像百度的統計代碼類似,所以我們每個頁面的加載的時候,都會統計到數據;然而在單頁應用,頁面加載初始化只有一次,所以其它頁面的統計數據需要我們自己手動上報

解決方案

使用 vue-routerbeforeEach 或者 afterEach 鉤子上報數據,具體使用哪個最好是根據業務邏輯來選擇。

const analyticsRequest = (to, from) => {
  // 只統計頁面跳轉數據,不統計當前頁 query 不同的數據
  // 所以這里只使用了 path, 如果需要統計 query 的,可以使用 to.fullPath
  if (to.path !== from.path) {
    analytics.request({
      url: `${location.protocol}//${location.host}${to.path}`
    });
  }
};

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    // 這里做登錄等前置邏輯判斷
    // 判斷通過之后,再上報數據
    ...
    analyticsRequest(to, from);
  } else {
    // 不需要判斷的,直接上報數據
    analyticsRequest(to, from);
    next();
  }
});

在組件中使用我們的自定義指令

使用過濾器實現展示信息格式化

如下圖中獎金數據信息,我們需要將后臺返回的獎金格式化為帶兩位小數點的格式,同時,如果返回的金額是區間類型,需要額外加上 字和 金額符號

在入口文件 main.js 中配置我們自定義的過濾器

Vue.filter("money", (value, config = { unit: "¥", fixed: 2 }) => {
  const moneyStr = `${value}`;
  if (moneyStr.indexOf("-") > -1) {
    const scope = moneyStr.split("-");
    return `${config.unit}${parseFloat(scope[0]).toFixed(config.fixed).toString()} 起`;
  } else if (value === 0) {
    return value;
  }

  return `${config.unit}${parseFloat(moneyStr).toFixed(config.fixed).toString()}`;
});

在組件中使用:

{{detail.priceScope | money}}

比率:{{detail.commissionRateScope}}%

獎金:{{detail.expectedIncome | money}}

axios 使用配置

在項目中,我們使用了 axios 做接口請求

在項目中全局配置 /api/common.js

import axios from "axios";
import qs from "qs";
import store from "../store";

// 全局默認配置
// 設置 POST 請求頭
axios.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
// 配置 CORS 跨域
axios.defaults.withCredentials = true;
axios.defaults.crossDomain = true;

// 請求發起前攔截器
axios.interceptors.request.use((config) => {
  // 全局 loading 狀態,觸發 loading 效果
  store.dispatch("updateLoadingStatus", {
    isLoading: true
  });
  
  // POST 請求參數處理成 axios post 方法所需的格式
  if (config.method === "post") {
    config.data = qs.stringify(config.data);
  }
  
  // 這句不能省,不然后面的請求就無法成功發起,因為讀不到配置參數
  return config;
}, () => {
  // 異常處理
  store.dispatch("updateLoadingStatus", {
    isLoading: false
  });
});

// 響應攔截
axios.interceptors.response.use((response) => {
  // 關閉 loading 效果
  store.dispatch("updateLoadingStatus", {
    isLoading: false
  });

  // 全局登錄過濾,如果沒有登錄,直接跳轉到登錄 URL
  if (response.data.code === 300) {
    // 未登錄
    window.location.href = getLoginUrl();
    return false;
  }

  // 這里返回的 response.data 是被 axios 包裝過的一成,所以在這里抽取出來
  return response.data;
}, (error) => {
  store.dispatch("updateLoadingStatus", {
    isLoading: false
  });
  return Promise.reject(error);
});

// 導出
export default axios;

然后我們在接口中使用就方便很多了 /api/xxx.js

import axios from "./common";

const baseURL = "/api/profile";
const USER_BASE_INFO = `${baseURL}/getUserBaseInfo.json`;
const UPDATE_USER_INFO = `${baseURL}/saveUserInfo.json`;

// 更新用戶實名認證信息
const updateUserInfo = userinfo => axios.post(UPDATE_USER_INFO, userinfo);

// 獲取用戶基礎信息
const getUserBaseInfo = () => axios.get(USER_BASE_INFO);
vuex 狀態在響應式頁面中的妙用

由于項目是響應式頁面,PC 端和移動端在表現成有很多不一致的地方,有時候單單通過 CSS 無法實現交互,這個時候,我們的 vuex 狀態就派上用場了,

我們一開始在 App.vue 里面監聽了頁面的 resize 事件,動態的更新 vuex 里面 isMobile 的狀態值

window.onresize = throttle(() => {
 this.updatePlatformStatus({
   isMobile: isMobile()
 });
}, 500);

然后,我們在組件層,就能響應式的渲染不同的 dom 結構了。其中最常見的是 PC 端和移動端加載的圖片需要不同的規格的,這個時候我們可以這個做

methods: {
  loadImgAssets(name, suffix = ".jpg") {
    return require(`../assets/images/${name}${this.isMobile ? "-mobile" : ""}${suffix}`);
  },
}



// 動態渲染不同規格的 dislog

下圖分別是 PC 端和移動短的表現形式,然后配合 CSS 媒體查詢實現各種布局

開發相關配置 反向代理

在項目目錄的 config 文件下面的 index.js 配置我們的本地反向代理和端口信息

dev: {
  env: require("./dev.env"),
  port: 80,
  autoOpenBrowser: true,
  assetsSubDirectory: "static",
  assetsPublicPath: "/",
  proxyTable: {
    "/api/profile": {
      target: "[真實接口地址]:[端口號]", // 例如: http://api.xxx.com
      changeOrigin: true,
      pathRewrite: {
        "^/api/profile": "/profile"
      }
    }
    ...
  },

然后我們調用接口的形式就會變成如下映射,當我們調用 /api/profile/xxxx 的時候,其實是調用了 [真實接口地址]/profile/xxxx

/api/profile/xxxx => [真實接口地址]/profile/xxxx

nginx 配置

upstream api.xxx.com
{
 #ip_hash;
  server [接口服務器 ip 地址]:[端口];
}

server {
  ...
  location ^~ /api/profile {
    index index.php index.html index.html;
    proxy_redirect off;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://api.xxx.com;
    
    rewrite ^/api/profile/(.*)$ /profile/$1 break;
  }
  ...
}
線上部署

如果路由使用的是 history 模式的話,需要在 nginx 里面配置將所有的請求到轉發到 index.html

nginx.conf 或者對應的站點 vhost 文件下面配置

location / {
    try_files $uri $uri/ /index.html;
}
優化

開啟靜態資源長緩存

location ~ .*.(gif|jpg|jpeg|png|bmp|swf|woff|ttf|eot|svg)$ {
    expires 1y;
}

location ~ .*.(js|css)$ {
    expires 1y;
}

開啟靜態資源 gzip 壓縮

// 找到 nginx.conf 配置文件
vim /data/nginx/conf/nginx.conf

gzip on;
gzip_min_length  1k;
gzip_buffers     4 8k;
gzip_http_version 1.1;
gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css;

開啟了 gzip 壓縮之后,頁面資源請求大小將大大減小,如下圖所示,表示已經開啟了 gzip 壓縮

Q&A

文章到這就結束了,如果有遺漏或者錯誤的地方,歡迎私信指出。
希望這篇文章能帶給大家一絲絲收獲。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/51217.html

相關文章

  • vue2.0 項目開發小結

    摘要:項目架構項目目錄項目目錄是采用自動生成,其它按需自己新建就好了。 項目架構 項目目錄 ├── build ├── config ├── dist │?? └── static │?? ├── css │?? ├── fonts │?? ├── images │?? ├── js │?? └── lib ├── src │?? ├── api │?...

    wuyangnju 評論0 收藏0
  • vue2.0 項目開發小結

    摘要:項目架構項目目錄項目目錄是采用自動生成,其它按需自己新建就好了。 項目架構 項目目錄 ├── build ├── config ├── dist │?? └── static │?? ├── css │?? ├── fonts │?? ├── images │?? ├── js │?? └── lib ├── src │?? ├── api │?...

    1treeS 評論0 收藏0
  • Vue2.0利用vue-resource上傳文件到七牛

    摘要:年底,公司項目番茄表單的前端部分,開始了從傳統的到的徹底重構。上傳流程圖不重要看文字事件觸發后,先去如果是圖片,可以同時通過以及將圖片預覽在頁面上后臺請求七牛的上傳,將拿到的和以及通過傳遞過來的一起到中。 關于上傳,總是有很多可以說道的。16年底,公司項目番茄表單的前端部分,開始了從傳統的jquery到vue 2.0的徹底重構。但是上傳部分,無論是之前的傳統版本,還是Vue新版本,都是...

    lcodecorex 評論0 收藏0
  • 推送近期三波關于Vue.js的資訊

    摘要:原文來自集前端最近很火的框架資源定時更新,歡迎一下。推送自己整理近期三波關于的資訊這里就拋磚引玉了,望有更屌的資源送助攻。 原文來自:集web前端最近很火的vue2框架資源;定時更新,歡迎Star一下。 推送自己整理近期三波關于Vue.js的資訊; 這里就拋磚引玉了,望有更屌的資源送助攻。 showImg(https://segmentfault.com/img/bVVeiZ); 第...

    Anonymous1 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<