diskgeniusv4.4.0_vue3.0(ant design vue 2.0) 实践记录

一.安装vue3.0(https://v3.vuejs.org/)

1.首先保证vue cli 的版本,我的版本是@vue/cli 4.5.1 ,如果版本低需要升级一下。升级命令:yarn global add @vue/cli to update

2.创建项目:可以采用界面方式创建(在终端输入vue ui),也可以在命令行创建(在终端输入 vue create dome),注意在创建项目的时候选择3.x版本

3.如果创建项目时你选择的时scss,运行的时候可能会报错:Module build failed (from ./node_modules/sass-loader/dist/cjs.js),意思是找不到sass-loader, 你可以npm rebuild node-sass,然后再运行项目,不出意外就可以运行了。

二.安装 ant design vue 2.0

  1. npm i --save ant-design-vue@next(Ant Design Vue), 配置按需加载,首先安装插件:npm install babel-plugin-import --save-dev , 在项目根目新建bable.config.js , 在里面输入
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ],
  plugins: [
    [
      "import",
      { libraryName: "ant-design-vue", libraryDirectory: "es", style: true }
    ]
  ],
};

2.我建议新建一个文件来配置需要引入那些组件

在src目录下新建utils文件,在utils文件下新建ant.js,内容如下:

import {
  Button,
} from "ant-design-vue";
const ant = {
  install(Vue) {
    Vue.component(Button.name, Button);
  },
};
export default ant;

在main.js 引入ant.js

import ant from "./utils/ant";
createApp(App).use(store).use(router).use(ant).mount('#app')

以上方法是将你用到的ant组件全局引入,一般比较常用的组件,可以这样引用,如果说,某个组件,你只用了一次,你也可以在局部引入,如果你配置了路由的按需加载,这样做会减少首屏的加载速度。局部引入如下:

import Button from "ant-design-vue/lib/button";
在
 components: {
    Button,
  },

3. 安装less-loader, 因为ant 使用的是less,所以需要:

npm install less less-loader --save-dev

配置less-loader :在项目根目录创建vue.cofing.js 输入下面内容:

module.exports = {

  css: {
    modules: false,
    loaderOptions: {
      sass: {
      },
      less: {
        lessOptions: {
          javascriptEnabled: true,
        },
      },
    },
  },
};

4. 测试:在HelloWorld.vue写入(把介绍删了):

<template>
<div class="hello">
  <h1>{{ msg }}</h1>
  <a-button type="primary">按钮</a-button>
</div>
</template>

你会在页面看到

d00efb1a140bfc6da54c7ad9d3b8375e.png

到此vue3.0和ant design vue 2.0的安装和配置就完了

3.Vue3.0和2.x在项目使用中有什么不同?

.我这里要讲的是在使用中,不是介绍两者的原理(我还没有使用vue3.0和ant design vue 2.0做过任何上线项目

1,2.x使用构造函数new Vue(...)创建实例,3.x使用createApp函数创建实例;

2.x(3.x不能这样用)

import Vue from "vue";
import App from "./App.vue";
import router from "@/router";
import store from "@/store";
// 引入vue ant design
import ant from "./utils/ant";
Vue.use(ant);
new Vue({
  router,
  store,
  render: h => h(App),
}).$mount("#app");

3.x

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
//全局 引入 ant 组件
import ant from "./utils/ant";
createApp(App).use(store).use(router).use(ant).mount('#app')

2. data、methods、computed、watch、props和setup 的比较

在很长一段事件我以为vue3.0不能使用2.x的 data、methods、computed、watch了,后来看到尤大的知乎回答,vue3.0兼容vue2.x的绝大部分api和属性方法,setup的组合式API只是拓展的,你可以用(最好是用),也可以不用。基本上完全兼容

下面我们来比较 一下他们的差别

做一个计数的例子:

(1).声明两个变量:

2.x 在data声明(3.x一样可以用)

 data() {
    return {
      num:1,
       obj:{
         name:"vue2"
    }
  },

3.x 使用 reactive处理对象的双向绑定,ref处理js基础类型的双向绑定, 不处理就不是响应式(可以不处理),使用reactive和ref处理过的数据可以在this中访问到,steup没有this,但是vue2.x的方法里有。

先引入ref、reactive
import {ref,reactive,computed} from "vue";

 setup(props) {
    let numx = ref(1);
    const obj = reactive({
      objx: {
        name: "vue3",
      },
    });
    return {
      numx,
      ...obj,
    };
  },

(2)该变数值

2.x(3.x一样可以用)

 methods: {
    add() {
      this.num++;
      this.numx++;//ref处理过了,methods里可以访问的到
    },
  },

3.x

  setup(props) {
    let numx = ref(1);
    const obj = reactive({
      objx: {
        name: "vue3",
      },
    });
    //定义的方法  setup访问不到data定义的数据
    const addx = () => {
      numx.value++;
    };
    return {
      numx,
      ...obj,
      addx,
    };
  },

(3)计算数值的变化(computed)

2.x(3.x一样可以用)

  computed: {
    com() {
      return this.num * 2;
    },
  },

3.x ,需要引入computed传入get 函数和set函数(可以不传)

import {ref,reactive,computed} from "vue";
 
setup(props) {
    let numx = ref(1);
    const obj = reactive({
      objx: {
        name: "vue3",
      },
    });
    let comx = computed({
      get: () => {
        return numx.value * 2;
      },
    });
    const addx = () => {
      numx.value++;
    };
    return {
      numx,
      ...obj,
      addx,
      comx,
    };
  },

(4)观察数组的变化(watch)

2.x(3.x一样可以用)

  watch: {
    num: {
      deep: true, //开启深度监听
      immediate: false, //上来就观察计算
      handler(a, b) {
        this.obj.name = `vue2变化了:${this.num}`;
      },
    },
  },

3.x 还是要先引入watch, 给watch传入两个参数,第一个是传入要观察哪个值,第二个是改触发的函数

 watch(
      () => numx.value,//这里直接传numx.value不行,传函数可以
      () => {
        obj.objx.name = `vue3变化了${numx.value}`;
      }
    );

**值得注意的是filters已经弃用。

3。 Router的使用

import { createRouter,
 createWebHistory,
 createWebHashHistory 
} from 'vue-router'
import Home from '../views/Home.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]
const router = createRouter({
  history: createWebHashHistory(),//hash模式//createWebHistory(process.env.BASE_URL) 历史模式
  routes
})
function newFunction() {
  localStorage.setItem("router", JSON.stringify(children));
}

export default router

router,基本上没有变,只不过把方法按需引入了,链式路由跳转,之前的一样可以用,但是在setup里面就不能用了,因为setup里面没有this的概念来看一下对比:

2.x(3.x一样可以用)

 methods: {
    add() {
      this.num++;
      this.numx++;
      this.$router.push("/about");
    },
  },

3.x 还是要先引入

import {useRouter} from "vue-router";
   setup(props) {
    const router = useRouter();
    const addx = () => {
      router.push("/about");
    };
    return {
      numx,
      ...obj,
      addx,
      comx,
    };
  },

4. vuex的使用

vuex还是和之前一样用,在setup 还是要引入

2.x(3.x一样可以用)

 created() {
    console.log(this.$store.state.open);
    this.$store.commit("changOpne", true);
  },

3.x

import {useStore} from "vuex";
  setup(props) {
    const store = useStore();
    console.log(store.state.open);
    store.commit("changOpne", false);
  },

vuex的辅助函数 mapState,mapGetters,mapMutations,mapActions一样可以使用,但是在setup里面我没有实验成功,如果谁知道怎么用,请在评论区赐教!

5.在添加vue全局属性

2.x(vue3.x不能用)

Vue.prototype.$http = () => {}

3.x

app.config.globalProperties.$http = () => {}

6. vue生命周期

官方文档(https://v3.vuejs.org/api/options-lifecycle-hooks.html#beforecreate)

我需要说的是setup 在created和beforeCreate前面执行

4.数据请求axios(axios中文文档|axios中文网)

1.安装npm i -s axios

2.封装axios

在utils新建request.js

import axios from "axios";
let baseURL = "/api/";
const service = axios.create({
  baseURL,
  timeout: 5000 // request timeout 
});
service.interceptors.request.use(
  config => {
    // 如果有token 就携带tokon
    let token = window.localStorage.getItem("accessToken");
    if (token) {
      config.headers.common.Authorization = token;
    }
    return config;
  },
  error => Promise.reject(error)
);
// 响应拦截器
service.interceptors.response.use(
  response => {
    const res = response.data;

    if (response.status !== 200) {
      return Promise.reject(new Error(res.message || "Error"));
    } else {在
      return res;
    }
  },
  error => {
    console.log("err" + error); // for debug
    return Promise.reject(error);
  }
);
export default service;

在vue.cofing.js配置请求代理:

  devServer: {
    host: 'localhost',//target host
    port: 8080,
    open: true,
    //proxy:{'/api':{}},代理器中设置/api,项目中请求路径为/api的替换为target
    proxy: {
      '/api': {
        target: "http://123.56.85.24:5000/",//代理地址,这里设置的地址会代替axios中设置的baseURL http://123.56.85.24:5000/
        changeOrigin: true,// 如果接口跨域,需要进行这个参数配置
        //ws: true, // proxy websockets
        pathRewrite: {
          '^/api': '/api'
          //pathRewrite: {'^/api': '/'} 重写之后url为 http://192.168.1.16:8085/xxxx
          //pathRewrite: {'^/api': '/api'} 重写之后url为 http://192.168.1.16:8085/api/xxxx
        }
      }
    }
  },

在src目录下,新建接口请求文件夹api,新建test.js文件

import request from "../utils/request.js";

// 文章列表
export function article() {
  return request({
    url: "/profile ",
    method: "get",
  });
}

测试接口:

在HelloWorld.vue 引入

import {
  article
} from "../api/test.js";

  setup(props) {
    const getData = async () => {
      const data = await article();
      console.log(data);
    };
    getData();
  },

打开控制台会看到一个数组,表示接口访问成功。

5.webpack打包优化

目前为止,我们项目的基本配置都完成了,我们打包看一下实际项目有多大在终端输入npm run build

打开dist简介:

ac9596f944e55f85ef900752a5829adc.png

可以看到包的大小是2.9MB,什么都就这么大了。

我们先看看看优化后的大小

990d0da047122b4c876da866cd2bea80.png

优化后是200K。啥也不说了上代码

const CompressionWebpackPlugin = require("compression-webpack-plugin");
const IS_PRODUCTION = process.env.NODE_ENV === "production";
const path = require("path");
function resolve(dir) {
  return path.join(__dirname, dir);
}
const cdn = {
  css: [],
  js: [
  ],
};
// const host = window.location.host;
console.log(IS_PRODUCTION);
const externals = {

};
module.exports = {


  publicPath: "./",
  outputDir: "dist",
  assetsDir: "static",
  indexPath: "index.html",
  productionSourceMap: false, // 关闭sourceMap
  devServer: {
    host: 'localhost',//target host
    port: 8080,
    open: true,
    //proxy:{'/api':{}},代理器中设置/api,项目中请求路径为/api的替换为target
    proxy: {
      '/api': {
        target: process.env.BASE_URL,//代理地址,这里设置的地址会代替axios中设置的baseURL http://123.56.85.24:5000/
        changeOrigin: true,// 如果接口跨域,需要进行这个参数配置
        //ws: true, // proxy websockets
        pathRewrite: {
          '^/api': '/api'
          //pathRewrite: {'^/api': '/'} 重写之后url为 http://192.168.1.16:8085/xxxx
          //pathRewrite: {'^/api': '/api'} 重写之后url为 http://192.168.1.16:8085/api/xxxx
        }
      }
    }
  },
  lintOnSave: false,
  configureWebpack: {
    // Webpack配置
    devtool: "none", // webpack内关闭sourceMap
    optimization: {
      // 优化配置
      splitChunks: {
        chunks: "all",
        cacheGroups: {
          // 拆分Vue
          vue: {
            test: /[/]node_modules[/]vue[/]/,
            name: "chunk-vue",
          },
        },
      },
    },
    resolve: {
      alias: {
        "@": resolve("src"), // 主目录
        "views": resolve("src/views"), // 页面
        'components': resolve("src/components"), // 组件
        'api': resolve("src/api"), // 接口
        'utils': resolve("src/utils"), // 通用功能
        'assets': resolve("src/assets"), // 静态资源
        'style': resolve("src/style"), // 通用样式
      },
    },
  },
  chainWebpack(config) {
    if (IS_PRODUCTION) {
      config.plugin("html").tap(args => {
        args[0].cdn = cdn;
        return args;
      });
      config.externals(externals);
      config.plugin("html").tap(args => {
        args[0].minify.minifyCSS = true;
        return args;
      });
      // gzip需要nginx进行配合
      config
        .plugin("compression")
        .use(CompressionWebpackPlugin)
        .tap(() => [
          {
            test: /.js$|.html$|.css/, // 匹配文件名
            threshold: 10240, // 超过10k进行压缩
            deleteOriginalAssets: true, // 是否删除源文件,这里最好不要删除
          }
        ]);
    }
  },
  css: {
    // 是否使用css分离插件 ExtractTextPlugin
    extract: !!IS_PRODUCTION,
    // 开启 CSS source maps?
    sourceMap: false,
    // css预设器配置项
    // 启用 CSS modules for all css / pre-processor files.
    modules: false,
    loaderOptions: {
      sass: {
      },
      less: {
        lessOptions: {
          javascriptEnabled: true,
        },
      },
    },
  },
};

cdn里面并没有东西,是因为我没有找到最新的vue全家桶的 cdn,如果你有资源,只需要向下面这样写就行:

const cdn = {
  css: [],
  js: [
    "https://cdn.bootcss.com/vue/2.6.10/vue.min.js",
    "https://cdn.bootcss.com/vue-router/3.0.3/vue-router.min.js",
    "https://cdn.bootcss.com/vuex/3.1.0/vuex.min.js",
    "https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.min.js",
  ],
};
const externals = {
  vue: "Vue",
  "vue-router": "VueRouter",
  vuex: "Vuex",
  axios: "axios",
};

开启gzip,服务器一定要配置gzip,我推荐不要删除原来的文件。不删除源文件包的大小大概在800k左右

以上代码地址:huoqingzhu/vue3.0-ant2.0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值