admin管理员组

文章数量:1531767

说明:Vuejs进阶版继承Vuejs基础版

上一篇:Vuejs基础版

下一篇:Vuejs补充版

目录大纲二

  • 十一、组件化开发
    • 1、组件化的实现和使用步骤
      • 1.1、什么是组件化?
      • 1.2、Vue组件化思想
      • 1.3、注册组件的基本步骤
      • 1.4、组件创建原理
    • 2、全局组件和局部组件
    • 3、父组件和子组件
    • 4、注册组件语法糖
      • 4.1、全局组件注册的语法糖
      • 4.2、局部组件注册的语法糖
    • 5、组件模板抽离写法
    • 6、父子组件的通信
    • 7、父传子——props数据验证
    • 8、子传父——自定义事件
    • 9、父子组件的访问
      • 9.1、父组件访问子组件:使用 $children 或 $refs
      • 9.2、子组件访问父组件:使用 $parent 或 $root
    • 10、插槽 slot :抽取共性,保留不同
      • 10.1、插槽的基本使用
      • 10.2、具名插槽的使用
      • 10.3、编译作用域与作用域插槽的使用
  • 十二、模块化开发
    • 1、CommonJS 导入与导出
    • 2、ES模块化的导入与导出
      • 2.1、导出
        • 导出变量
      • 2.2、导入
      • 2.3、export default
  • 十三、webpack
    • 1、初识 webpack
    • 2、安装使用 webpack
      • 2.1、webpack 的基本使用
      • 2.2、webpack.config.js配置和package.json配置
    • 3、webpack中使用css文件的配置
    • 4、less 文件处理
    • 5、webpack-图片文件处理
    • 6、ES6语法转换成ES5 - babel
    • 7、webpack 配置Vue
      • 7.1、安装配置使用Vue
      • 7.2、组件中使用组件
      • 7.3、小Tips:在导入文件时省略后缀名,需在`webpack.config.js`中做修改:
    • 8、webpack 的 plugin插件
      • 8.1、添加版权的 Plugin
      • 8.2、打包 html 的 plugin
      • 8.3、js压缩的 Plugin
      • 8.4、小TIps:使用该插件压缩js时,会将注释也删除,所以添加版权的插件与该插件两者不互存
    • 9、webpack-dev-server搭建本地服务器
    • 10、webpack 配置文件的分离
  • 十四、Vue CLI 脚手架
    • 1、vuecli脚手架介绍和安装
      • 1.1、介绍
      • 1.2、安装
      • 1.3、目录结构详解
    • 2、Vue程序运行过程
    • 3、VueCLI3
      • 3.1、VueCLI 创建项目和目录
      • 3.2、目录结构详解
      • 3.3、vueCLI3配置文件的查看和修改
    • 4、箭头函数的使用和 this 的指向
  • 十五、Vue-Router
    • 1、认识路由
      • 1.1、URL 的 hash
      • 1.2、HTML5 的 history 模式:pushState
      • 1.3、HTML5 的 history 模式:replaceState
      • 1.4、HTML5 的 history 模式:go
    • 2、vue-router 基本使用
      • 2.1、安装和使用 vue-router
      • 2.1、路由的默认路径
      • 2.3、router-link 属性
    • 3、vue-router 动态路由
      • 3.1、路由的懒加载
      • 3.2、懒加载的方式
    • 4、vue-router 嵌套路由
      • 4.1、实现嵌套路由的两个步骤
    • 5、vue-router 参数传递
      • 5.1、准备工作
      • 5.2、传递参数的方式
      • 5.3、传递参数 —— JavaScript代码
    • 6、vue-router 导航守卫
    • 7、keep-alive
  • 十六、TabBar
    • 1、TarBar案例的实现
    • 2、TarBar案例的实现思路
    • 3、给 TabBarItem 传入 active 图片
  • 十七、Promise 的使用
    • 1、Promise的三种状态
    • 2、Promise链式调用的三种简写
    • 3、Promise 的 all 方法的使用
  • 十八、Vuex
    • 1、单界面状态管理的实现
    • 2、多界面状态管理
    • 3、插件 vuex-devtools
    • 4、mutations
      • 4.1、mutations 是定义方法
      • 4.2、Mutation中的参数
    • 5、vuex - getters
    • 6、vuex-数据的响应式原理
  • 响应式管理
    • 7、vuex-actions
    • 8、vuex-modules
      • 8.1、是什么
      • 8.2、怎么做
      • 8.3、vuex-modules中的相关属性
    • 9、对象的解构
    • 10、Vuex的安装与使用

十一、组件化开发

1、组件化的实现和使用步骤

1.1、什么是组件化?

如果将一个复杂的问题,拆分成很多个可以处理的小问题,再将其放在整体当中,就会将问题迎刃而解
组件的定义:实现应用中局部功能代码和资源的集合
组件化思想:将一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么整个页面的管理和维护就变得非常容易了

1.2、Vue组件化思想

组件树:

1.3、注册组件的基本步骤

组件的使用分成三个步骤:

  1. 创建组件构造器
  2. 注册组件
  3. 使用组件

  1. Vue.extend():
    • 调用 Vue.extend() 创建的是一个组件构造器
    • 通常在创建组件构造器时,传入 template 代表我们自定义组件的模板
    • 该模板就是在使用到组件的地方,要显示的HTMl代码
  2. Vueponent():
    • 调用Vueponent() 是将刚才的组件构造器注册为一个全局组件,并且给它起一个组件的标签名称。
    • 所以需要传递两个参数:1、注册组件的标签名 2、组件构造器
  3. 组件必须挂载在某个Vue实例下,否则它不会生效

1.4、组件创建原理

Vue组件创建原理:https://blog.csdn/qq_53810245/article/details/122894319

2、全局组件和局部组件

3、父组件和子组件

组件嵌套:https://blog.csdn/qq_53810245/article/details/122891352

app 管理所有父组件,父组件中再嵌套子组件

理解:在root组件中定义父级组件,在父级组件中定义子组件,从而形成调用关系

4、注册组件语法糖

4.1、全局组件注册的语法糖

4.2、局部组件注册的语法糖

5、组件模板抽离写法

一般使用第二张模板

6、父子组件的通信

在开发中,旺旺一些数据需要从上层传递到下层:比如在一个页面中,我们从服务器请求到了很多的数据。其中一部分数据,并非是我们整个页面的大组件来展示,而是需要下面的子组件进行展示,这个时候,并不会让子组件再次发送一个网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)
通过 props 【properties属性】向子组件传递数据,通过事件向父组件发送消息

7、父传子——props数据验证

<div id="app">
  <cpn :c-Info="info"></cpn>
</div>
<template id="cpn">
  <h2>{{cInfo.name}}</h2>
</template>
<script src="../js/vue.js"></script>

<script>
  const cpn = {
    template:'#cpn',
    props:{
      cInfo:{
        type:Object,
        default() {
          return {};
        }
      }
    }
  }
  const app = new Vue({
    el: '#app',
    data: {
      info:{
        name:'why',
        age:18,
        height:1.88
      }
    },
    components:{
      cpn
    }
  })
</script>

8、子传父——自定义事件

当子组件需要向父组件传递数据时,就要用到自定义事件】
自定义事件的流程

  • 在子组件中,通过$emit()来触发事件
  • 在父组件中,通过v-on 来监听子组件事件
<!--父组件的模板-->
<div id="app">
  <cpn @itemclick="cpnClick"></cpn>
</div>
<!--子组件模板-->
<template id="cpn">
  <div>
    <button v-for="item in categories"
            @click="btnClick(item)">
      {{item.name}}
    </button>
  </div>
</template>
<script src="../js/vue.js"></script>
<script>
  // 1. 子组件
  const cpn = {
    template:'#cpn',
    data(){
      return{
        categories:[
          {id:101,name:'热门推荐'},
          {id:102,name:'手机数码'},
          {id:103,name:'电脑办公'},
          {id:104,name:'家用家电'},
        ]
      }
  },
    methods:{
      btnClick(item){
        // console.log(item.id);
        // 发射事件:自定义事件,自定义发出的函数,自定义的参数
        this.$emit('itemclick',item);
      }
    }
  }
  // 2. 父组件
  const app = new Vue({
    el:'#app',
    components:{
      cpn
    },
    methods: {
      cpnClick(item){
        console.log('cpnClick',item)
      }
    }
  })
</script>

9、父子组件的访问

9.1、父组件访问子组件:使用 $children 或 $refs

- $ children 的访问
	- this.$children 是一个数组类型,它包含所有子组件对象![在这里插入图片描述](https://img-blog.csdnimg/e7bade92e09946d1a75aaf8dd64fd56d.png)

9.2、子组件访问父组件:使用 $parent 或 $root

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>子访问父-parent-root</title>
</head>
<body>
<!--父组件的模板-->
<div id="app">
  <cpn></cpn>
</div>
<!--子组件的模板-->
<template id="cpn">
  <div>
    <h2>我是子组件</h2>
    <button @click="btnClick">按钮</button>
  </div>
</template>
<script src="../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊',
    },
    // 注册子组件
    components:{
      cpn:{
        template:'#cpn',
        methods:{
          btnClick(){
          //  1.访问父组件 $parent,获取到的层级关系是VueComponents,以上为Vue实例
          //   console.log(this.$parent);

          //  2. 访问根组件$root,获取到的是Vue实例
            console.log(this.$root.message);
          }
        }
      }
    },
  })
</script>

</body>
</html>

10、插槽 slot :抽取共性,保留不同

  • slot 译为插槽,例如电脑的USB插槽、插板中的电源插槽
  • 插槽的目的是让我们原有的设备更多的扩展性
  • 组件的插槽
    • 组件的插槽是为了让我们封装的组件更加具有扩展性
    • 让使用者可以决定组件内部的一些内容到底展示什么
  • 插槽的应用:
    • 移动网站中的导航栏
    • 导航栏会封装成一个插件,比如 nav-bar 组件
    • 一旦有了这个组件,我们就可以在多个页面中复用了

10.1、插槽的基本使用

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>slot-插槽的基本使用</title>
</head>
<body>

<div id="app">
  <cpn ref="ref"></cpn>
  <cpn><button>跳转</button></cpn>
  <cpn><button>点击</button></cpn>
  <cpn><input type="text"></cpn>
</div>

<template id="cpn">
  <div>
    <h2>我是子组件</h2>
    <p>我是组件哈哈哈</p>
<!--    预留插条,并在cpn标签下进行自行定义使用-->
<!--    <slot></slot>-->
<!--    插条中也可以使用 默认的值,如重新定义插条中的内容即可覆盖原默认内容-->
    <slot><button>按钮</button></slot>

  </div>
</template>
<script src="../js/vue.js"></script>

<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊',
    },
    methods:{},
    // 注册组件
    components:{
      cpn:{
        template:'#cpn',
        data(){
          return{}
        }}}
  })
</script>
</body>
</html>

10.2、具名插槽的使用

  • 具名插槽:具有名字的插条
  • 作用:针对 slot 插槽编排名字,可以实现指定替换
<div id="app">
  <AAA>
  	<span slot="center">更改</span>
  </AAA>
</div>
<template id="cpn">
<!--  <div>
    <h2>这行代码我是不会更改的</h2>
    <slot><button>默认按钮</button></slot>
  </div>-->
  <div>
    <slot name="left"><span></span></slot>
    <slot name="center"><span></span></slot>
    <slot name="right"><span></span></slot>
    <slot></slot>
  </div>
</template>
<script src="../js/vue.js"></script>

<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: '你好啊',
    },
    components:{
      cpn:{
        template:'#cpn'
      }
    }
  })
  • 如果想要在插槽中存放多个内容但又不想用一个div将他们包裹起来,可以用如下方法,但必须添加绑定
  • 父组件
  • 子组件

10.3、编译作用域与作用域插槽的使用

  • 编译作用域:在哪里定义的变量只会在它的作用域下进行查找调用

  • 官方解释:父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子集作用域内编译

  • 作用域插槽的使用:父组件替换插槽的标签,但是内容由子组件来提供

  • 例如:

十二、模块化开发

前言:随着 ajax 异步请求的出现,慢慢形成了前后端的分离
模块化的核心:导入与导出

1、CommonJS 导入与导出

2、ES模块化的导入与导出

导入导出使用前提:

2.1、导出

导出变量
  • 方式一:边定义边导出
    export var num = 1000 
    export let name = 'why'
    export const height = 1.88
    // 导出函数/类:
    export function sum(num1,num2){
      return num1 + num2
    }
    export class Person{
      constructor(name,age) {
        this.name = name;
        this.age = age;
      }
      run(){
        console.log(this.name + '在奔跑');
      }
    }
    
  • 方式二:先定义后导出
    var num = 1000 
    let name = 'why'
    const height = 1.88
    
    // 导出函数/类:
    function sum(num1,num2){
      return num1 + num2
    }
    class Person{
      constructor(name,age) {
        this.name = name;
        this.age = age;
      }
      run(){
        console.log(this.name + '在奔跑');
      }
    }
    export {num,name,height,sum,Person}
    

2.2、导入

import{num1,height} from "./aaa.js";
或 统一全部导入
import * as all from "./aaa.js";
console.log(all.flag)

2.3、export default

  • 某些情况下,给函数或功能不命名,在导入的时候导入者自己命名
    需注意: export defalut 在同一个模块中,不允许同时存在多个
export default function (args){
  console.log(args);
}


导入
import fun from './aaa.js'
fun('快快打印')

十三、webpack

webpack 是JavaScript应用的静态模块打包工具

webpack 为了可以正常运行,必须依赖 node 环境,node环境为了可以正常的执行很多代码,必须其中包含各种依赖的包, npm 工具就是 node packages manager

1、初识 webpack

前端模块化的方案:AMD、CMD、CommonJs、ES6

webpack 与 grunt / gulp 的对比:

  1. grunt / gulp 的核心是 Task
    • 配置一系列的 task,并且定义 task 要处理的事务(例如ES6、ts转化、图片压缩、scss转成css)
    • 之后让 grunt / gulp 来依次执行这些task,而且让整个流程自动化,grunt / gulp 也被称为前端自动化任务管理工具
  2. 举例:gulp 的task
    • 下面的 task 就是将src下面的所有js文件转成ES5的语法,并且最终输出到dist文件夹中
  const gulp = require('gulp');
  const babel = require('gulp-babel');
  
  gulp.task('js',()=>
    gulp.src('src/*.js')
      .pipe(babel({
        presets:['es2015']
      }))
      .pipe(gulp.dest('dist'))
  );
  1. 什么时候用 grunt / gulp ?
    • 如果你的工程模块依赖非常简单,甚至没有用到模块化的概念
    • 只需要进行简单的合并、压缩,就使用 grunt / gulp 即可
    • 但是如果整个项目使用了模块化管理,而且相互依赖非常强,我们就可以使用更加强大的 webpack 了
  2. grunt / gulp 和 webpack 有什么不同呢?
    • grunt / gulp 更加强调的是前端流程的自动化,模块化不是它的核心
    • webpack 更加强调模块化开发管理,而文件压缩合并、预处理等功能,是他附带的功能

2、安装使用 webpack

2.1、webpack 的基本使用

切记:命令行敲命令一定要在对应的目录文件下才能生效

  • 查看node版本:node -v
  • 全局安装 webpack,指定自己依赖的版本号:npm install webpack@3.6.0 -g
  • 查看webpack版本:webpack --version
  • 该文件夹下建立dist文件夹以及src/main.js文件和src/mathUtils.js文件和index.html文件
mathUtils.js
function add(num1,num2){
  return num1 + num2
}
function mul(num1,num2){
  return num1 * num2
}
// 1、commonjs 导出
module.exports = {
  add,mul
}


info.js
// ES6的导出语法
export const name = 'why';
export const age = 18;
export const height = 1.88;



main.js
// 1、使用commonjs的模块化导入
const {add,mul} = require('./mathUtils')
// 打印
console.log(add(1, 2));
console.log(mul(2, 3));

// 2、使用ES6的模块化导入
import {name, age, height} from './info';
console.log(name, age, height);

  • 一般的启动方式:webpack .\src\main.js .\dist\bundle.js
    直接从 index.html 中引入即可:<script src="./dist/bundle.js"> </script>

2.2、webpack.config.js配置和package.json配置

  • 在该文件夹下新建webpack.config.js文件

    // 导入模块,从node包里进行导入
    const path = require('path')
    
    module.exports = {
      //入口:可以是字符串/数组/对象/,这里的入口只写一个,所以写一个字符串即可
      entry:'./src/main.js',
      //出口:通常是一个对象,里面至少包含两个重要属性,path和filename
      output:{
        // 动态的获取路径,此处获取的是绝对路径。resolve()对路径进行拼接,__dirname获取当前路径
        path: path.resolve(__dirname,'dist'),
        filename:'bundle.js'
      }
    }
    
  • npm初始化,生成package.json:npm init

  • 根据package.json 文件中的依赖进行相对应的安装:npm install

  • 如果想要执行 npm run build,,需要先在package.json文件中添加至脚本script中

    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "build": "webpack"
      },
    
  • 局部安装webpack,开发时依赖

    第一步:局部安装
    cd 对应目录
    npm install webpack@3.6.0 --save-dev
    第二步:启动webpack ,使用局部的 webpack
    node_moules/.bin/webpack
    

3、webpack中使用css文件的配置

踩坑:1、要在该文件夹目录下进行局部配置,2、使用管理员身份运行webstorm
loader 使用过程:点击跳转官网学习

  • 在src目录中创建一个 css 文件,在其中创建一个normal.css文件

  • 步骤一:通过 npm 安装需要使用的 loader

    npm install --save-dev css-loader@2.0.2
    
  • 步骤二:在 webpack.config.js 下进行配置

    module.exports = {
    	module: {
    	    rules: [
    	      {
    	        test: /\.css$/,
    	        use: ["style-loader", "css-loader"],
    	      },
    	    ],
    	  },
    }
    
  • 在 main.js 中导入

    // 1、使用  commonjs 的模块化规范
    const {add,mul} = require('./js/mathUtils.js')
    
    console.log(add(20, 30));
    console.log(mul(20, 30));
    
    // 2、 使用ES6的模块化的规范
    import {name,height,age} from "./js/info.js";
    console.log(name);
    console.log(age);
    
    // 3.依赖css文件
    require('./css/normal.css')
    
  • 安装 style-loader

    npm install --save-dev style-loader@0.23.1
    
  • npm run build 运行

4、less 文件处理

项目中会使用 less、css、stylus来写样式

  • 创建一个 css / special.less 文件,放在 css 文件中

    @fontSize:50px;
    @fontColor:orange;
    
    body{
      font-size: @fontSize;
      color: @fontColor;
    }
    
  • main.js 中引入

    // 1、使用commonjs的模块化导入
    const {add,mul} = require('./js/mathUtils')
    // 使用
    console.log(add(1, 2));
    console.log(mul(2, 3));
    
    // 2、使用ES6的模块化导入
    import {name, age, height} from './js/info';
    console.log(name, age, height);
    
    //3.依赖 css 文件
    require('./css/normal.css')
    
    // 4.依赖less文件
    require('./css/special.less')
    document.writeln('<h2>余婷的背景是红色</h2>')
    
  • 安装 loader:npm install --save-dev less-loader@4.1.0 less@3.9.0

  • 在 webpack.config.js 文件中的 rules 中选项配置相关内容

    // webpack.config.js
    module.exports = {
        ...
        module: {
            rules: [{
                test: /\.less$/,
                use: [{
                    loader: "style-loader" // creates style nodes from JS strings
                }, {
                    loader: "css-loader" // translates CSS into CommonJS
                }, {
                    loader: "less-loader" // compiles Less to CSS
                }]
            }]
        }
    };
    

5、webpack-图片文件处理

  • 在n ormal.css 文件中引入图片路径如下:

    body{
    	background:url("../img/test.jpg");
    }
    
  • 安装 loader:npm install --save-dev url-loader

  • 在 webpack.config.js 中进行配置 rules 选项

    {
            test: /\.(png|jpg|gif)$/,
            use: [
              {
                loader: 'url-loader',
                options: {
                  limit: 8192
                }
              }
            ]
          }
    
  • 当图片小于 8kb 时

  • 当图片大于 8kb 时,就要安装 file-loader:npm install --szve-dev file-loader

  • 再次打包 npm run build时,就会发现dist文件下多了一个图片文件

6、ES6语法转换成ES5 - babel

  • babel 的使用:npm install --save-dev babel-loader@7 babel-core@6.26.3 babel-preset-es2015@6.24.1

  • 配置 webpack.config.js 文件,rules 选项中添加如下配置

     rules: [
        {
          test: /\.js$/,
          // exculde:排除,include:包含
          exclude: /(node_modules|bower_components)/,
          use: {
            loader: 'babel-loader',
            options: {
              presets: ['es2015']
            }
          }
        }
      ]
    
  • 使用 npm run build打包执行,发现所有ES6语法皆变成了ES5的语法

7、webpack 配置Vue

7.1、安装配置使用Vue

  • npm 安装 Vue :npm install vue@2.5.21 --save

  • 【该步骤已被替换,可直接进行下一步操作】新建 src / vue / app.js 文件,并写入组件内容并导出

    export default {
      template:`
        <div id="app">
          <h2>我正在学习Vue开发{{message}}</h2>
          <button @click="btnClick">按钮</button>
          <h2>{{name}}正在学习Vue开发</h2>
        </div>`,
      data(){
        return{
          message:'Hello Webpack',
          name:'Mark'
        }
      },
      methods:{
        btnClick(){
          console.log('被点击事件');
        }
      }
    }
    
  • 【该步骤已被替换,可直接进行下一步操作】新建 src / vue / App.vue 的vue component文件,并在相应内容块中写入相应组件内容

    <template>
      <div>
        <h2 class="title">我正在学习Vue开发{{message}}</h2>
        <button @click="btnClick">按钮</button>
        <h2>{{name}}正在学习Vue开发</h2>
      </div>
    </template>
    
    <script>
    export default {
      name: "App",
      data(){
        return{
          message:'Hello Webpack',
          name:'Mark'
        }
      },
      methods:{
        btnClick(){
          console.log('被点击事件');
        }
      }
    }
    </script>
    
    <style scoped>
      .title{
        color: green;
      }
    </style>
    
  • 在 main.js 文件中导入 Vue 及组件 APP 使用

    // 5.使用vue开发
    import Vue from 'vue'
    // import App from './vue/app' 该方法已被注释,同上
    import App from "./vue/App.vue";
    new Vue({
      el:'#app',
      template:`<App/>`,
      // 注册组件
      components:{
        App
      }
    })
    
  • 在页面 index.html 中写入id为app的挂载

    <div id="app"></div>
    
  • 在 webpack.config.js 中配置

    model.exports= {
    	resolve:{
    	    // alias:别名
    		alias: {
    		      'vue$': 'vue/dist/vue.esm.js'
    		    }
    		 }
    }
    
  • 安装 vue-loader 和 vue-template-compiler 作为解析:
    npm install vue-loader@13.0.0 vue-template-compiler@2.5.21 --save-dev

  • 执行 npm run build 进行运行

7.2、组件中使用组件

  • 新建 src / vue / Cpn.vue 的vue component文件

    <template>
      <div>
        <h2>我是组件中的小组件</h2>
        <p>我是Cpn组件的内容</p>
        <h2>{{name}}</h2>
      </div>
    </template>
    
    <script>
    export default {
      name: "Cpn",
      data(){
        return{
          name:'Cpn组件的name'
        }
      }
    }
    </script>
    
    <style scoped>	
    </style>
    
  • 新建 src / vue / App.vue 的vue component文件

    <template>
      <div>
        // 原组件内容
        <h2 class="title">我正在学习Vue开发{{message}}</h2>
    	// 使用字组件
        <Cpn></Cpn>
      </div>
    </template>
    
    <script>
      // 导入子组件 Cpn
      import Cpn from './Cpn.vue'
      export default {
        name: "App",
        components:{
          Cpn
        },
        data(){
          return{
            message:'Hello Webpack',
          }
        },
      }
    </script>
    
    <style scoped>
    </style>
    

7.3、小Tips:在导入文件时省略后缀名,需在webpack.config.js中做修改:

8、webpack 的 plugin插件

plguin 是插件的意思,通常是用于对某个现有的架构进行扩展
webpack 中的插件,就是对webpack 现有功能的各种扩展,比如打包优化,文件压缩等等

loader 和 plugin 区别

  • loader 主要用于转换某些类型的模块,它是一个转换器
  • plugin 是插件,它是对 webpack 本身的扩展,是一个扩展器
    plugin 的使用过程:
    步骤一:通过 npm 安装需要使用的 plugins (某些webpack已经内置的插件不需要安装)
    步骤二:在webpack.config.js中的plugins中配置插件

8.1、添加版权的 Plugin

  • 导入 webpack 模块并使用Plugins设置版权

  • bundle.js 文件效果为:
/*! 最终版权归aaa所有 */
/******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
。。。。。。

8.2、打包 html 的 plugin

  • HtmlWebpackPlugin插件可以自动生成一个 index.html(可以指定模板来生成);并将打包的 js 文件,自动通过 script 标签插入到 body中

  • 安装:npm install html-webpack-plugin@3.2.0 --save-dev

  • 注释掉默认文件路径

  • 使用:在 webpackconfig文件下修改如下,并 npm run build 运行

8.3、js压缩的 Plugin

  • 使用第三方插件
    npm install uglifyjs-webpack-plugin@1.1.1 --save-dev

  • 修改 webpack.config.js文件,使用插件:然后执行 npm run build

  • 查看打包后的 bunlde.js 文件,是已经被压缩过的

8.4、小TIps:使用该插件压缩js时,会将注释也删除,所以添加版权的插件与该插件两者不互存

9、webpack-dev-server搭建本地服务器

  • 安装:npm install webpack-dev-server@2.9.3 --save-dev

  • 配置 webpack.config.js 文件

    // 导入模块,从node包里进行导入
    const path = require('path')
    const webpack = require('webpack')
    const HtmlWebpackPlugin = require('html-webpack-plugin')
    const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin')
    
    module.exports = {
      entry:'./src/main.js',
      resolve: {...},
      output:{...},
      module: {...},
      plugins:[...],
      devServer:{
        contentBase:'./dist',// 为哪一个文件夹提供本地服务,默认是根文件夹./dist
        inline:true, // 页面实时刷新
        /*以下内容可添可不添
        port:端口号,默认跑在8080端口
        historyApiFallback:在SPA页面中,依赖HTML5的history模式
        */
      }
    }
    
  • 在package.json文件中添加如下脚本,--open 可直接将生成的链接打开:

  • npm run server 执行文件,在生成的端口如下

  • 优点是不再重新打包运行,而是当调试完毕后在运行 npm run build进行打包

10、webpack 配置文件的分离

  • 进行抽离:开发时依赖一个文件,运行时依赖另一个文件,即用三个配置文件完成一个配置文件的使用

  • 建立文件夹build用来存放配置文件,基础配置 base.config.js文件,开发时的配置 dev.config.js文件,生产时的配置 prod.config.js文件

  • 即开发时要用 dev.config.js + base.config.js,生产时要用 prod.config.js + base.config.js

  • 抽离完之后,使用他们就需要合并文件,分支合并到主干需要用到插件:npm install webpack-merge@4.1.5 --save-dev

  • 合并与导出如下,prod.config.jsdev.config.js文件都需要执行合并与导出

    prod.config.js 文件
    const baseConfig = require('./base.config')
    // 将合并后的内容导出
    module.exports = webpackMerge(baseConfig,{
      plugins:[
        new UglifyjsWebpackPlugin()
      ]
    })
    
    dev.config.js 文件
    // 导入所需要的模块
    const webpackMerge = require('webpack-merge')
    const baseConfig = require('./base.config')
    module.exports = webpackMerge(baseConfig,{
      devServer:{
        contentBase:'./dist',
        inline:true
      }
    })
    
  • 在 package.json文件中配置如下属性:

  • 改动生成的dist文件的路径如下:修改base.config.js中的path

十四、Vue CLI 脚手架

对文章进行了重新整理,详情点击跳转:https://blog.csdn/qq_53810245/article/details/122901321

1、vuecli脚手架介绍和安装

1.1、介绍

Vue CLI 官网:https://cli.vuejs/zh/

  • 使用 Vue.js 开发大型应用,需要考虑代码目录结构、项目结构和部署、热加载、代码单元测试等事情。我们通常会使用一些脚手架工具来帮助完成这事情
  • CLI 是 Command-Line Interface,译为命令行界面,俗称脚手架
  • 使用 vue-cli 可以快速搭建Vue开发环境以及对应的webpack配置

1.2、安装

环境要求:Node 环境要求 8.9 以上

  • 安装 Vue 脚手架:npm install -g @vue/cli@3.2.1
  • 拉取 2.x 模板(旧版本):
    npm install -g @vue/cli-init@3.2.0
    # `vue init`的运行效果将会跟`vue-cli@2.x`相同
    vue init webpack my-project
    
  • Vue CLI2 初始化项目:vue init webpack my-project
    Vue CLI3 初始化项目:vue create my-project
    Vue 全家桶:VueCore + vue-route + vuex
  • 创建Vue项目:vue init webpack vuecli2test相关配置如下:

1.3、目录结构详解

2、Vue程序运行过程



3、VueCLI3

3.1、VueCLI 创建项目和目录

3.2、目录结构详解

3.3、vueCLI3配置文件的查看和修改

启动配置服务器——vue图形化GUI界面:vue ui

4、箭头函数的使用和 this 的指向

箭头函数的使用:当我们准备用一个函数作为参数传到另外一个函数中使用时
点击链接查看详解

十五、Vue-Router

1、认识路由

路由:通过互联网的网络把信息从源地址传输到目的地址的活动
官网:https://router.vuejs/zh/

1.1、URL 的 hash

1.2、HTML5 的 history 模式:pushState

1.3、HTML5 的 history 模式:replaceState

1.4、HTML5 的 history 模式:go


2、vue-router 基本使用

  • vue-router 是Vue.js 官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用
  • 官方网站为:https://router.vuejs/zh/
  • vue-router 是基于路由和组件的,路由用于设定访问路径,将路径和组件映射起来
  • 在 vue-router 的单页面应用中,页面的路径的改变就是组件的切换

2.1、安装和使用 vue-router

  • 安装 vue-router:npm install vue-router --save
  • 在模块化工程中使用它(因为是一个插件,所以可以通过Vue.use()来安装路由功能)
    • 第一步:导入路由对象,并且调用 Vue.use(VueRouter)
    • 第二步:创建路由实例,并且传入路由映射配置
    • 第三步:在Vue实例汇总挂载创建的路由实例
  • 使用 vue-router 的步骤:
    • 第一步:创建路由组件 learnvuerouter/src/components/Home.vue

      	<template>
        <div>
          <h2>我是关于</h2>
          <p>我是首页内容,哈哈哈</p>
        </div>
      </template>
      
      <script>
      export default {
        name: "home"
      }
      </script>
      
      <style scoped>
      
      </style>
      
    • 第二步:配置路由映射,learnvuerouter/src/router/index.js

      import Vue from 'vue'
      import Router from 'vue-router'
      // import HelloWorld from '@/components/HelloWorld'
      
      import Home from '../components/Home'
      import About from "../components/About";
      
      // 1.通过 Vue.use(插件),安装插件
      Vue.use(Router)
      
      // 2.创建VueRouter对象
      const routes = [
        {
          path: '/home',
          component: Home
        },
        {
          path:'./about',
          component:About
        }
      ]
      
      export default router
      
    • 第三步:使用路由:通过<router-link><router-view>learnvuerouter/src/router/index.js

      <template>
        <div id="app">
          <router-link to="/home">首页</router-link>
          <router-link to="/about">关于</router-link>
          <router-view></router-view>
        </div>
      </template>
      
      <script>
      export default {
        name: 'App'
      }
      </script>
      
      <style>
      
      </style>
      

2.1、路由的默认路径

2.3、router-link 属性

  • <router-link to="/home">首页</router-link>:用于指定跳转的路径
  • <router-link to="/about" tag="button">关于</router-link>:指定 <router-link> 之后渲染成什么组件,默认是 a标签,但此处更改为 button 标签
  • <router-link to="/home" replace>首页</router-link>:在指定 replace 的情况下,后退键返回不能返回到上一个页面中

3、vue-router 动态路由

3.1、路由的懒加载

  • 当打包构建应用时,Javascript 包会变得非常大,影响页面加载
  • 如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效
  • 路由懒加载的主要作用就是将路由对应的组件打包成一个个的js代码块
  • 只有在这个路由被访问到的时候,才加载对应的组件
  • 未进行路由懒加载的效果

  • 进行了路由懒加载之后的效果

3.2、懒加载的方式

const Home = ()=> import('../components/Home')

E:\html\WebStorm\project\project_Vuejs\LearnVuejs03\learnvuerouter\src\router\index.js 下修改使用懒加载方式

import Vue from 'vue'
import Router from 'vue-router'
// import HelloWorld from '@/components/HelloWorld'
/*
import Home from '../components/Home';
import About from "../components/About";
import User from "../components/User";
*/
// 路由懒加载方式导入路由
const Home = ()=> import('../components/Home')
const About = ()=> import('../components/About')
const User = ()=> import('../components/User')

// 1.通过 Vue.use(插件),安装插件
Vue.use(Router)

// 2.创建VueRouter对象
const routes = [
  {
    // 默认路径
    path:'',
    // redirect 重定向
    redirect:'/home'
  },
  {
    path: '/home',
    component: Home
  },
  {
    path:'/about',
    component:About
  },
  {
    path:'/user/:userId',
    component: User
  }
]
const router = new Router({
  // 配置路由和组件之间的应用关系
  routes,
  mode:'history'
})

/*export default new Router({
  routes: [

  ]
})*/

// 3.将 router 对象传入到Vue实例
export default router

4、vue-router 嵌套路由

4.1、实现嵌套路由的两个步骤

  • 创建对应的子组件E:\html\WebStorm\project\project_Vuejs\LearnVuejs03\learnvuerouter\src\components\HomeNews.vue

    <template>
    <div>
      <ul>
        <li>新闻1</li>
        <li>新闻2</li>
        <li>新闻3</li>
        <li>新闻4</li>
      </ul>
    </div>
    </template>
    
    <script>
    export default {
      name: "HomeNews"
    }
    </script>
    
    <style scoped>
    
    </style>
    
  • 在路由映射中配置对应的子路由,可以添加默认路径作为默认显示:E:\html\WebStorm\project\project_Vuejs\LearnVuejs03\learnvuerouter\src\router\index.js

    	// 路由懒加载方式导入路由
    const Home = ()=> import('../components/Home')
    const HomeNews = ()=>import('../components/HomeNews')
    const HomeMessage = ()=>import('../components/HomeMessage')
    ...
    const routes = [
      /*添加默认路径*/
      {
        path: '',
        redirect: 'news'
      },
      {
        // 默认路径
        path:'',
        // redirect 重定向
        redirect:'/home'
      },
      {
        path: '/home',
        component: Home,
        // 配置子路由关系
        children:[
          {
            path:'news',
            component: HomeNews
        },
          {
            path: 'message',
            component: HomeMessage
          }
        ]
      },
      {
        path:'/about',
        component:About
      },
      {
        path:'/user/:userId',
        component: User
      }
    ]
    
  • 在组件内部使用<router-view>标签:E:\html\WebStorm\project\project_Vuejs\LearnVuejs03\learnvuerouter\src\components\Home.vue

    <template>
      <div>
        <h2>我是首页</h2>
        <p>我是首页的内容,哈哈哈</p>
        <router-link to="/home/news">新闻</router-link>
        <router-link to="/home/message">消息</router-link>
        <router-view></router-view>
      </div>
    </template>
    

5、vue-router 参数传递

5.1、准备工作

  • 创建新的组件 Profile.vue

  • 配置路由映射

  • 添加跳转的 <router-link>

5.2、传递参数的方式

  • 方式一:params

    • 配置路由格式:/router/:id
    • 传递的方式:在 path 后面跟上对应的值
    • 传递后形成的路径:/router/123,/router/abc
  • 方式二:query

    • 新建E:\html\WebStorm\project\project_Vuejs\LearnVuejs03\learnvuerouter\src\components\Profile.vue
    <template>
    <div>
      <h2>我是Profile组件内容</h2>
      <h2>{{$route.query}}</h2>
      <h2>{{$route.query.name}}</h2>
      <h2>{{$route.query.age}}</h2>
      <h2>{{$route.query.height}}</h2>
    </div>
    </template>
    
    <script>
    export default {
      name: "Profile"
    }
    </script>
    
    • 设置index.js

    • E:\html\WebStorm\project\project_Vuejs\LearnVuejs03\learnvuerouter\src\App.vue中添加组件并显示,传递后形成的路径:/router?id=123,/router?id=abc

<router-link :to="'/user/'+userId">用户</router-link>

<router-link :to="{path:'/profile',query:{name:'why',age:18,height:1.88}}">档案</router-link>

5.3、传递参数 —— JavaScript代码

<template>
  <div id="app">
    <router-link to="/home">首页</router-link>
    <router-link to="/about">关于</router-link>
<!--
    <router-link :to="'/user/'+userId">用户</router-link>
&lt;!&ndash;    <router-link to="/profile">档案</router-link>&ndash;&gt;
    <router-link :to="{path:'/profile',query:{name:'why',age:18,height:1.88}}">档案</router-link>
-->

<!--    另外一种写法-->
    <button @click="userClick">用户</button>
    <button @click="profileClick">档案</button>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'App',
  data(){
    return{
      userId:'lisi'
    }
  },
  methods:{
    userClick(){
      this.$router.push('/user/' + this.userId)
    },
    profileClick(){
      this.$router.push(
        {
          path:'/profile',
          query:{
            name:'kobe',
            age:18,
            height:1.88
          }
        }
      )
    }

  }
}
</script>

6、vue-router 导航守卫

E:\html\WebStorm\project\project_Vuejs\LearnVuejs03\learnvuerouter\src\router\index.js

在该文件下

  • 调用 beforeEach 函数

  • 在 VueRouter对象中设置元数据作为导航的实现

    // 2.创建VueRouter对象
    const routes = [
      {
        // 默认路径
        path:'',
        // redirect 重定向
        redirect:'/home'
      },
      {
        path: '/home',
        component: Home,
        // 元数据
        meta:{
          title:'首页'
        },
        // 配置子路由关系
        children:[
          /*添加默认路径*/
          {
            path: '',
            redirect: 'news'
          },
          {
            path:'news',
            component: HomeNews
        },
          {
            path: 'message',
            component: HomeMessage
          }
        ]
      },
      {
        path:'/about',
        component:About,
        // 元数据
        meta:{
          title:'关于'
        },
      },
      {
        path:'/user/:userId',
        component: User,
        // 元数据
        meta:{
          title:'用户'
        },
      },
      {
        path:'/profile',
        component:Profile,
        // 元数据
        meta:{
          title:'档案'
        },
      }
    ]
    

7、keep-alive

作用:所有路径匹配到的视图组件都会被缓存,即保存上次浏览记录,可以使被包含的组件保留状态,或 避免重新渲染

十六、TabBar

1、TarBar案例的实现

  • npm init webpack tabbar,创建项目,目录结构如下

  • 在base.css中设置基础样式,即清除浏览器自带样式

  • TabBarItem.vue 设置插槽并设置样式并导出

    <template>
      <div class="tab-bar-item">
        <slot name="item-icon"></slot>
        <slot name="item-text"></slot>
    <!--    <img src="../../assets/img/tabbar/shouye.svg" alt="">
        <div>首页</div>-->
      </div>
    </template>
    
    <script>
    export default {
      name: "TabBarItem"
    }
    </script>
    
    <style scoped>
      .tab-bar-item {
        flex: 1;
        text-align: center;
        height: 49px;
        font-size: 14px;
      }
      .tab-bar-item img{
        width: 24px;
        height: 24px;
        margin-top: 3px;
        /*将图片的默认3px去掉*/
        vertical-align: middle;
      }
    </style>
    
  • TabBar.vue 中设置插槽并导出

    <template>
      <div id="tab-bar">
    <!--    设置插槽-->
        <slot></slot>
      </div>
    </template>
    
    <script>
    export default {
      name: "TabBar"
    }
    </script>
    
    <style scoped>
      #tab-bar {
        display: flex;
        background-color: #f6f6f6;
    
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        /*设置阴影:x方向,y方向,阴影宽度,阴影颜色*/
        box-shadow: 0 -1px 1px rgba(100,100,100,.1);
      }
    
    </style>
    
  • App.vue 中导入、注册、使用组件

    <template>
      <div id="app">
    <!--    3、使用组件-->
        <tab-bar>
          <tab-bar-item>
            <img slot="item-icon" src="./assets/img/tabbar/shouye.svg" alt="">
            <div slot="item-text">首页</div>
          </tab-bar-item>
          <tab-bar-item>
            <img slot="item-icon" src="./assets/img/tabbar/profile.svg" alt="">
            <div slot="item-text">分类</div>
          </tab-bar-item>
          <tab-bar-item>
            <img slot="item-icon" src="./assets/img/tabbar/gouwuche.svg" alt="">
            <div slot="item-text">购物车</div>
          </tab-bar-item>
          <tab-bar-item>
            <img slot="item-icon" src="./assets/img/tabbar/wode.svg" alt="">
            <div slot="item-text">我的</div>
          </tab-bar-item>
        </tab-bar>
      </div>
    </template>
    
    <script>
      /*1、导入组件*/
      import TabBar from "./components/tabbar/TabBar";
      import TabBarItem from "./components/tabbar/TabBarItem";
      export default {
        name: 'App',
        components:{
          /*2、注册组件*/
          TabBar,
          TabBarItem
        }
      }
    </script>
    
    
    <style>
      /*导入基本样式*/
      @import "./assets/css/base.css";
    </style>
    

2、TarBar案例的实现思路

  • 1、封装TarBar组件

    • 自定义TarBar组件,在App中使用
    • 让TarBar处于底部,并且设置相关的样式
  • 2、TarBar中显示的内容由外界决定

    • 定义插槽
    • flex布局平分TarBar
  • 3、自定义TabBarItem.vue,可以传入图片和文字

    • 定义TarBarItem,并且定义两个插槽:图片、文字
    • 给两个插槽外层包装 div,用于设置样式
    • 填充插槽,实现底部TarBar的效果
    <template>
    <!--  所有的Item都展示同一个图片,同一个文字-->
      <div class="tab-bar-item" @click="itemClick">
        <div v-if="!isActive"><slot name="item-icon"></slot>
        </div>
        <div v-else><slot name="item-icon-active"></slot>
        </div>
        <div :style="activeStyle">
          <slot name="item-text"></slot>
        </div>
      </div>
    </template>
    <script>
    export default {
      name: "TabBarItem",
      props:{
        path:String,
        activeColor:{
          type:String,
          default:'red'
        }
      },
      data(){
        return {
          // isActive:true
        }
      },
      /*搞一个计算属性*/
      computed:{
        isActive(){
          /*拿到活跃路由的path与当前路径的path作为对比*/
          /*
          * /home -> item1(/home) = true
          * /home -> item2(/category) = false
          * indexOf()方法:寻找,找到的话不为-1*/
          return this.$route.path.indexOf(this.path) !== -1
        },
        activeStyle(){
          return this.isActive ? {color:this.activeColor} :{}
        }
      },
      methods:{
        itemClick(){
          this.$router.replace(this.path);// 该方法允许返回
        }
      }
    }
    </script>
    
    <style scoped>
      .tab-bar-item {
        /*使盒子都有相同的长度*/
        flex: 1;
        text-align: center;
        height: 49px;
        font-size: 14px;
      }
      .tab-bar-item img{
        width: 24px;
        height: 24px;
        margin-top: 3px;
        /*将图片的默认3px去掉*/
        vertical-align: middle;
      }
    /*  !*设置 active 下的状态*!
      .active{
        color: red;
      }*/
    </style>
    
  • 4、App.vue 使用组件

    	  <template>
    	  <div id="app">
    	<!--    3、使用组件-->
    	    <tab-bar>
    	      <tab-bar-item path="/home" activeColor="deeppink">
    	        <img slot="item-icon" src="./assets/img/tabbar/home.svg" alt="">
    	        <img slot="item-icon-active" src="./assets/img/tabbar/home_active.svg" alt="">
    	        <div slot="item-text">首页</div>
    	      </tab-bar-item>
    	      <tab-bar-item path="/category" activeColor="deeppink">
    	        <img slot="item-icon" src="./assets/img/tabbar/category.svg" alt="">
    	        <img slot="item-icon-active" src="./assets/img/tabbar/category_active.svg" alt="">
    	        <div slot="item-text">分类</div>
    	      </tab-bar-item>
    	      <tab-bar-item path="/cart" activeColor="deeppink">
    	        <img slot="item-icon" src="./assets/img/tabbar/cart.svg" alt="">
    	        <img slot="item-icon-active" src="./assets/img/tabbar/cart_active.svg" alt="">
    	        <div slot="item-text">购物车</div>
    	      </tab-bar-item>
    	      <tab-bar-item path="/profile" activeColor="deeppink">
    	        <img slot="item-icon" src="./assets/img/tabbar/profile.svg" alt="">
    	        <img slot="item-icon-active" src="./assets/img/tabbar/profile_active.svg" alt="">
    	        <div slot="item-text">我的</div>
    	      </tab-bar-item>
    	    </tab-bar>
    	    <router-view></router-view>
    	  </div>
    	</template>
    	
    	<script>
    	  /*1、导入组件*/
    	  import TabBar from "./components/tabbar/TabBar";
    	  import TabBarItem from "./components/tabbar/TabBarItem";
    	  export default {
    	    name: 'App',
    	    components:{
    	      /*2、注册组件*/
    	      TabBar,
    	      TabBarItem
    	    }
    	  }
    	</script>
    	
    	<style>
    	  /*导入基本样式*/
    	  @import "./assets/css/base.css";
    	</style>
    	
    	```
    	
    
  • 4、index.js 中设置相关属性

3、给 TabBarItem 传入 active 图片

  • 在 TabBarItem 组件中设置插槽用于存放图片以及文字,并设置active下的style属性为color:red
  • 在App.vue中设置两种状态下的的图片显示

文件路径的引用问题——取别名

情况二:HTML中的图片路径需要加~

十七、Promise 的使用

导读:Promise 是异步编程的一种解决方案【同步:sync,异步:async】

1、Promise的三种状态

  • pending :等待状态,比如正在进行网络请求,或者定时器没有到时间
  • fulfill :满足状态,当我们主动回调了 resolve 时,就处于该状态,并且会回调 .then()
  • reject :拒绝状态,当我们主动回调了 reject 时,就处于该状态,并且会回调 .catch()

    简写为如下:

2、Promise链式调用的三种简写

以 resolve 为例,reject同 resolve

最终可简写为:

3、Promise 的 all 方法的使用

十八、Vuex

官方解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式

  • 状态管理到底是什么?
    • 简单来说是将多个组件共享的变量全部存储在一个对象里面
  1. vue init webpack learnvuex:创建Vuex的项目
  2. npm install vuex@3.0.1 --save :安装Vuex

1、单界面状态管理的实现

2、多界面状态管理

  1. 创建store/index.js文件

  2. 导入、挂载并拿到store

  3. 创建 Hellovuex.vue 组件

  4. App.vue 中使用组件

    <template>
      <div id="app">
        <h2>{{message}}</h2>
    <!--    <h2>{{counter}}</h2>-->
        <h2>-------------App内容----------------</h2>
        <h2>{{$store.state.counter}}</h2>
        <button @click="$store.state.counter++">+</button>
        <button @click="$store.state.counter--">-</button>
        <h2>-------------App内容----------------</h2>
        <Hello-vuex/>
        <!--    <router-view/>-->
      </div>
    </template>
    
    <script>
    import HelloVuex from "./components/HelloVuex";
      export default {
        name: 'App',
        components:{
          HelloVuex
        },
        data(){
          return{
            message:'你好,从今天开始学习Vuex',
            // counter:0
          }
        }
      }
    </script>
    

3、插件 vuex-devtools

安装vuex-devtools :https://blog.csdn/qq_53810245/article/details/121295089

4、mutations

mutations 唯一的目的就是修改 state 中状态
mutations 中的每个方法尽可能完成的事件比较单一一点儿

4.1、mutations 是定义方法

修改state中的数据都是通过mutations去修改的
作用是:在浏览器中可以跟踪到数据的变化状况


在App.vue 中设置点击的方法,在方法中调用this.$storemit('increment)

  1. 从而使用index中设置的方法
  2. 通过 mutation更新

4.2、Mutation中的参数

  1. 参数被称为mutation的载荷(Payload)
  2. 参数可以是数,也可以是对象
  3. 第一步:写入按钮并设置点击事件
  4. 第二步:添加相关方法
  5. 在index.js中设置相关方法
    import Vue from "vue";
    import Vuex from 'vuex'
    import {stat} from "copy-webpack-plugin/dist/utils/promisify";
    // 1.安装插件
    Vue.use(Vuex)
    // 2.创建对象
    const store = new Vuex.Store({
      // 用于保存状态
      state:{
        counter:10,
        students:[
          {id:110,name:'why',age:18},
          {id:111,name:'koba',age:24},
          {id:112,name:'james',age:30},
          {id:113,name:'curry',age:10}
        ]
      },
      mutations:{
      //  定义方法,修改state中的数据都是通过mutations去修改的
    /*
    Mutation 状态主要包括两部分:
    - 字符串的事件类型(type)
    - 一个回调函数(handler),该回调函数的第一个参数就是state
    */
        increment(state){
          state.counter++
        },
        decrement(state){
          state.counter--
        },
        incrementCount(state,count){
          state.counter += count;
        },
        addStudent(state,stu){
          state.students.push(stu)
        }
      },
      // 做一些异步操作
      actions:{},
      // 类似于组组件中的计算属性
      getters:{
        powerCounter(state){
          return state.counter * state.counter
        },
        // 获取年龄大于20岁的集合
        more20stu(state){
          return state.students.filter(s=>s.age>20)
        },
        // 获取年龄大于20岁的集合的长度
        more20stuLength(state,getters){
          return getters.more20stu.length
        },
        // 获取年龄大于指定的岁数的集合
        moreAgestu(state,getters){
          return function (age){
            return state.students.filter(s => s.age >age )
          }
        //  将上述函数改为箭头函数为:
    /*      return age => {
            return state.students.filter(s => s.age > age)
          }*/
        }
      },
      // 划分模块
      modules:{}
    })
    // 3.导出 store对象
    export default store
    
  6. Mustation 提交风格,当为特殊提交封装时需要传入payload

5、vuex - getters

作用:当我们每次想要使用state经过变化之后的值时

  1. 在App.vue中使用getters

  2. index.js中写入相关函数

6、vuex-数据的响应式原理

Vuex的store中的state是响应式的,当state中的数据发生改变时,Vue组件会自动更新
但是需遵守一些Vuex对应的规则

  • 提前在store中初始化好所需的规则



响应式管理

响应式 - 添加: Vue.set(state.info,'address','洛杉矶')// 响应式的添加属性address

响应式 - 删除:Vue.delete(state.info,'age') // 响应式的删除age属性

  • 当给state中的对象添加新属性时,使用下面的方式
    • 方式一:使用Vue.set(obj,‘newProp’,123)
    • 方式二:用新对象给旧对象重新赋值

7、vuex-actions

异步操作不能在 Mutation中进行
Action类似于 Mutation ,但是是来代替 Mutation 进行异步操作的

8、vuex-modules

8.1、是什么

将 store 分割成模块(Modules),而某个模块拥有自己的 state、mutations、action、getters等

8.2、怎么做

那我们按照什么样的方式来组织模块呢?

8.3、vuex-modules中的相关属性


9、对象的解构

10、Vuex的安装与使用

  1. 安装:npm install vuex@3.1.0 --save
  2. 创建目录:src/store/index.js
  3. index.js中导入使用:
import Vue from 'vue'
import App from './App.vue'

//1. 安装插件
Vue.use(Vuex)
//2. 创建 Store 对象
const store = new Vuex.Store({
	state:{
	// 添加的商品
		cartList:[]
	},
	mutations:{
		 addCounter(state,payload){
			payload.count++;
		}
		addToCart(state,payload){
			state.cartList.push(payload)
		}
	},
	actions:{
		addCart(context,payload){
		// 1.payload :新添加的商品,判断与已加商品是否重复
			let oldProduct = null;
			for(let item of context.state.cartList){
				if(item.iid === payload.iid){
				oldProduct = item;
				}
			}
		// 步骤1 可以一步到位为以下内容:
		// let oldProduct = context.state.carList.find(item => item.iid === payload.iid)
		// 2.判断 oldProduct
			if(oldProduct){
				// oldProduct.count += 1;该方法无法跟踪
				context.commit('addCounter),oldProduct
			}else{
				payload.count = 1;
				// state.carList.push(payload);该方法无法跟踪
				context.commit('addToCart',payload)
			}			
		}
	}
})

// 3.挂载到 Vue 实例上
export default store

本文标签: 进阶篇章Vuejs