Vue(day11)

项目上线

对项目进行打包, 将打包后的内容,部署到服务器中
打包 : npm run build
把打好的包放到 http-server 里面,演示

第一次截图

  1. 介绍 vendor : 里面放一些第三方包 vue/vue-router/element-ui 包等
    只要不是我们自己写的代码,都属于第三方
  2. 优化 :
    2.1 优化打包的第三方 (CDN)
    2.2 按需加载

    首屏加载时间,是衡量一个网站性能快慢的很重要的一个指标,
    首屏加载时间越快,用户存留就越多,用户量就越高
    如何提高加载速度呢?
    //1. 只加载首屏中看到的内容, 没有看到的内容都不加载,需要用到的时候,再去加载
    //2. 进来减少首屏的请求次数
    //3. vue 项目打包的时候,如何实现按需加载功能 ?
    // 实现说明 : vue 的异步组件(路由) 配合 webpack 代码分割的功能,很容易实现按需加载功能
    // 如何在项目中,通过代码实现按需加载呢 ? 讲导入组件的位置, 改为动态加载

  1. 按需加载 : 参考 : vue-router => 路由栏加载
    const Home = () => import('@/components/Home/Home.vue')

  2. 打包查看 js 文件

第二次截取

  1. 查看多的 js 文件
  2. 重新打包运行,演示点击进入按需加载
  3. 打包 GoodsAdd 和 Goods 在一起的包
    const Goods = () =>
    import(/_ webpackChunkName:'goods' / '@/components/Goods/Goods.vue')
    const GoodsAdd = () =>
    import(/
    webpackChunkName:'goods' _/ '@/components/GoodsAdd/GoodsAdd.vue')

第三次截图

  1. 名字是 goods
  2. 文件也少了一个

CDN

为什么打包后,第三方文件体积很大,因为第三方文件比较多
如何优化 ?? 不再将第三方文件 打包到 dist, 但是, 项目中还是要是要第三方文件,我们通过一个在线的
的第三方文件路径, 来引入这个文件,(CDN)

  1. 在 index.html 引入 CDN 文件
  2. 在 webpack.base.conf.js
externals : {
  vue : 'Vue',
  "vue-router" : "VueRouter"
}
  1. 其他配置

  2. 以后使用 :
    4.1 bootstrap => bootCDN
    4.2 https://www.jsdelivr.com/
    4.3 官方文档


项目打包和优化

  • 打包命令:npm run build

按需加载

  • 1 修改 router/index.js 中导入组件的语法
// 使用:
const Home = () => import('@/components/home/Home');
// 替换:
// import Home from '@/components/home/Home'

// 给打包生产的JS文件起名字
const Home = () =>
  import(/* webpackChunkName: 'home' */ '@/components/home/Home');

// chunkName相同,将 goods 和 goods-add 两个组件,打包到一起
const Goods = () =>
  import(/* webpackChunkName: 'goods' */ '@/components/goods');
const GoodsAdd = () =>
  import(/* webpackChunkName: 'goods' */ '@/components/goods-add');
  • 2 (该步可省略)修改 /build/webpack.prod.conf.js 中的 chunkFilename
{
  // [name] 代替 [id]
  chunkFilename: utils.assetsPath('js/[name].[chunkhash].js');
}

使用 CDN

  • 开源项目 CDN 加速服务

  • 1 在 index.html 中引入 CDN 提供的 JS 文件

  • 2 在 /build/webpack.base.conf.js 中(resolve 前面)添加配置 externals

  • 注意:通过 CDN 引入 element-ui 的样式文件后,就不需要在 main.js 中导入 element-ui 的 CSS 文件了。所以,直接注释掉 main.js 中的导入 element-ui 样式即可

  • externals配置:

externals: {
  // 键:表示 导入包语法 from 后面跟着的名称
  // 值:表示 script 引入JS文件时,在全局环境中的变量名称
  vue: 'Vue',
  axios: 'axios',
  'vue-router': 'VueRouter',
  'element-ui': 'ELEMENT',

  BMap: 'BMap',
  echarts: 'echarts',
}

import ElementUI from 'element-ui'

常用包 CDN

Quill

<!-- Include the Quill library -->
<script src="https://cdn.bootcss.com/quill/1.3.4/quill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-quill-editor@3.0.4/dist/vue-quill-editor.js"></script>

<!-- Include stylesheet -->
<link
  href="https://cdn.bootcss.com/quill/2.0.0-dev.3/quill.core.min.css"
  rel="stylesheet"
/>
<link
  href="https://cdn.bootcss.com/quill/2.0.0-dev.3/quill.snow.min.css"
  rel="stylesheet"
/>
<link
  href="https://cdn.bootcss.com/quill/2.0.0-dev.3/quill.bubble.min.css"
  rel="stylesheet"
/>

Vuex

第一讲 : Vuex的介绍

vuex 是什么?

  • 状态管理工具

  • 状态即数据, 状态管理就是管理组件中的data数据

  • Vuex 中的状态管理工具,采用了 集中式 方式统一管理项目中组件之间需要通讯的数据

  • [看图]

如何使用

  • 最佳实践 : 只将组件之间共享的数据放在 vuex 中, 而不是将所有的数据都放在 vuex 中 ,
  • 也就是说:如果数据只是在组件内部使用的,这个数据应该放在组件中,而不要放在 vuex
  • vuex 中的数据也是响应式的,也就是说:如果一个组件中修改了 vuex 中的数据,另外一个使用的 vuex 数据的组件,就会自动更新 ( vuex 和 localstorage的区别)

什么时候用 ?

  • 官网

  • 说明: 项目体量很小,不需要使用 vuex, 如果项目中组件通讯不复杂,也不需要使用 vuex

  • 只有写项目的时候,发现组件通讯多,组件之间的关系复杂,项目已经无法继续开发了,此时,就应该使用 vuex

第二讲 : Vuex的基本使用

vuex的基本使用

  • 安装 : npm i vuex
  • 引入 : 引入 vuex 之前一定要先引入 vue
    • <script src="./node_modules/vuex/dist/vuex.js"></script>
  • 实例化 store
    • store 仓库 , 获取数据和操作数据都要经过 store
    • const store = new Vuex.Store()
  • 操作数据
    • 获取数据 : store.state.num
    • 操作数据 : store.state.num = 300
    • 虽然 store.state.count = 300 可以修改值 , 但是vuex 也有严格模式,
    • 添加严格模式 : strict : true,
  • 使用 mutations
    • 注册 : mutations : {}
    • increament(state) { state.count = 20; }
    • 默认第一个参数永远是 state
    • 触发事件 : store.commit('increament')

vuex的传参

  • 触发事件 :

  • # 传参最好传一个对象,多个值查看方便
    store.commit('increament', {
        num: 400
    })
    
  • 事件

  • # payload 载荷
    increament(state, payload) {
    	state.count = payload.num
    }
    

vue和vuex的配合使用

需求 : 有个h1显示数字的标题, 点击按钮累加数字

  • 先用vue做出来效果
  • 再用vuex和vue配合使用
    • 实例化vuex的store
    • 实例化vue
    • 把store挂载到vue上
  • 操作数据
    • h1展示数据 : <h1>{{ $store.state.num }}</h1>
    • 点击触发事件修改数据 : this.$store.commit('addNum')
    • addNum(state) { state.num++ }

第三讲 : Vue脚手架3.0

官网 : https://cli.vuejs.org/zh/guide/installation.html

安装 :

  • 安装脚手架 2.x : npm i vue-cli -g
  • 安装脚手架 3.x : npm i -g @vue/cli
  • 检测脚手架版本号 : vue -V / --version

创建一个项目

  • 命令 : vue create vuex-todos (可视化 vue ui)
  • 可以选择默认配置或者手动配置
  • 开发运行 : npm run serve
  • 发布构建 : npm run build

第四讲 : 使用Vuex改版 TodoMVC

  • 初始化项目

  • 拷贝模板(todomvc-app-template)里的结构(section部分)和样式 (node_modules里的)

  • 组件化

    • 创建 todo-header.vue / todo-list.vue / todo-footer.vue + scaf结构
    • app.vue 中 导入 : import todoheader from "./components/todo-header.vue";
    • 注册 : components: { todoheader ,todolist ,todofooter }
    • 使用 : <todofooter></todofooter>
  • 配置 vuex 管理 list

    • 创建文件夹 store/store.js

    • 安装 vuex

    • 引入

    • vue安装vuex : Vue.use(Vuex)

    • 实例store, 并且导出 store

    • main.js 中引入并挂载到 vue 上

  • 列表展示

  • 删除任务

  • 添加任务

  • 修改任务

  • 修改状态

  • 计算属性(三个)

  • 清除已经完成的任务

第四讲 : 如何使用 actions

  • 官网介绍
  • Action 类似于 mutation,不同在于:
    • Action 可以包含任意异步操作。
    • Action 提交的是 mutation,而不是直接变更状态。
  • mutaions 里不只能使用同步,不能出现异步 (演示删除任务 里使用setTimeout 会报错)
  • 演示1: actions 可以包含任意异步操作。 代码1
  • 演示2: actions 不能直接变更状态 , 代码2 会报错
  • 演示3 : actions 提交的是 mutation
# 都是 actions 里
//演示1 :
setTimeout(() => {
    console.log('actions')
}, 0)

// 演示2 :报错
setTimeout(() => {
    context.state.list = context.state.list.filter(
        item => item.id != payload.id
    )
}, 0)

// 演示3 : 提交 mutations
setTimeout(() => {
    context.commit('delTodo', payload)
}, 0)

第五讲 : 常用的几个辅助函数

mapGetters 辅助函数

  • store.js 中的几个计算属性 :

  • let getters = {
      isFooterShow(state) {
        return state.list.length > 0
      },
      itemLeftCount(state) {
        return state.list.filter(item => !item.done).length
      },
      isClearShow(state) {
        return state.list.some(item => item.done)
      }
    }
    
  • 使用 mapGetters

    • todo-footer.vue 中 引入 : import { mapGetters } from "vuex";

    • 将 store 中的 getter 映射到局部计算属性

      computed: { ...mapGetters(["isFooterShow", "itemLeftCount", "isClearShow"]) }-

    • 使用

      • 以前通过属性 : <footer v-show="$store.getters.isFooterShow">

      • 现在通过辅助函数 :<footer v-show="isFooterShow">

mapMutations 辅助函数

# 写在 methods
# 映射
...mapMutations(["delTodo", "updateTodo", "changeState"]),

 # 起别名 (防止当前所在的函数名和这个mutaions名一致,会导致死循环)
...mapMutations({
    deltodo: "delTodo",
    updatetodo: "updateTodo",
    changestate: "changeState"
}), 

# 以后使用  
  this.deltodo({id})  替代 :  this.$store.commit('delTodo',{ id })

mapActions 辅助函数

# 写在 methods
# 映射
...mapActions(["asyncDelTodo"]),
# 起别名    
    ...mapActions({
        aDT: "asyncDelTodo"
    }),
        
# 使用别名
  this.aDT({ id }); 
# 如果没有起别名
 this.asyncDelTodo({ id });  替换  this.$store.dispatch('asyncDelTodo',{id})

反向代理

一 : 说明

  • 解决跨域问题的方式 :
    • JSONP == > 只能处理 get 方式
    • CORS ==> 处理自己的服务器
    • 反向代理 ==> 也很常用
  • 说明
    1. 演示跨域问题
    2. 反向代理的原理
    3. 脚手架vue-cli 生成的项目中如何使用反向代理

二 : 演示跨域问题

测试真实请求接口 : https://douban.uieee.com/v2/movie/in_theaters

  1. todo-vuex 里的 app.vue 中 的js 代码区域演示

  2. 安装 axios

  3. 代码 :

    // 演示跨域问题
    /* eslint-disable */
    import axios from 'axios';
    
    axios.get('https://api.douban.com/v2/movie/in_theaters').then(res => {
      console.log(res)
    })
    
  4. 报错 :

    Access to XMLHttpRequest at 'https://api.douban.com/v2/movie/in_theaters' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
    
  5. 报错原因

    - 项目运行在  http://localhost:8080
      //  I  Your application is running here: http://localhost:8080  
    - 发送ajax请求 : //域名是 https://api.douban.com/v2/movie/in_theaters
    - 出现跨域问题
    

三 : 反向代理的原理

四 : 演示

  • 修改 config/index.js 配置文件
  proxyTable: {
      '/myapi': {
        // 代理的目标服务器地址
        // https://api.douban.com/v2/movie/in_theaters
        // /myapi/movie/in_theaters
        target: 'https://api.douban.com/v2',
        pathRewrite: { '^/myapi': '' },

        // 设置https
        secure: false,
        // 必须设置该项
        changeOrigin: true
      }
    },
  • 最终代码

    // axios.get('https://api.douban.com/v2/movie/in_theaters').then(res => {
    axios.get("http://localhost:8080/api/movie/in_theaters").then(res => {
      console.log(res);
    });
    
  • 最终配置 cli2.x :

      proxyTable: {
          '/myapi': {
            // 代理的目标服务器地址
            // https://api.douban.com/v2/movie/in_theaters
            // /myapi/movie/in_theaters
            target: 'https://api.douban.com/v2',
            pathRewrite: { '^/myapi': '' },
    
            // 设置https
            secure: false,
            // 必须设置该项
            changeOrigin: true
          }
        },
    
  • 最终配置 3.X

    • 根目录下 新建一个 vue.config.js
    • 拷贝如下代码
    module.exports = {
      devServer: {
        proxy: {
          '/myapi': {
            // 代理的目标服务器地址
            // https://api.douban.com/v2/movie/in_theaters
            // /myapi/movie/in_theaters
            target: 'https://douban.uieee.com/v2',
            pathRewrite: { '^/myapi': '' },
    
            // 设置https
            secure: false,
            // 必须设置该项
            changeOrigin: true
          }
        }
      }
    }
    
    # 使用
    axios.get('http://localhost:8080/myapi/movie/in_theaters').then(res => {
      console.log(res)
    })
    axios.get('/myapi/movie/in_theaters').then(res => {
      console.log(res)
    })
    
    
  • 重新启动 : npm run dev

posted @ 2020-05-11 23:51  handsomehe  阅读(180)  评论(0编辑  收藏  举报