Vue从入门到精通课程超详细

Vue2.0

1.认识Vue

1.创始人以及发展历程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IYmj7NzM-1679370213958)(笔记图片/image-20230306112147856.png)]

尤雨溪 (EvanYou)

美籍华人

Vue Technology LLC 创始人

高中:上海复旦大学附中

大学:纽约科尔盖特大学

发展历程

1.2014 年 2 月

尤雨溪开源了一个前端开发库 Vue.js。Vue.js 是构建 Web 界面的 JavaScript 库,也是一个通过简洁的 API 提供高效数据绑定和灵活组件的系统。

2.2016 年 9 月

在南京的 JSConf 上,尤雨溪正式宣布以技术顾问的身份加盟阿里巴巴 Weex 团队,来做 Vue 和 Weex 的 JavaScript runtime 整合,目标是让大家能用 Vue 的语法跨三端。

2020 年 4 月

Vue3.0beta版本测试发布。

2. Vue是什么?

Vue.js是一款轻量级的、以数据驱动的、前端JS框架,是一个通过简洁的API提供高效的数据绑定和灵活的组件系统

3.与Jquery的技术比较优势在哪里

旧:Jquery

操作DOM元素

jQuery是使用选择器($)选取DOM对象,对其进行赋值、取值、事件绑定等操作,其实和原生的HTML的区别只在于可以更方便的选取和操作DOM对象,而数据和界面是在一起的

复杂页面维护成本大

jquery则需要获取dom元素节点,并对dom进行添加一个标签的操作,如果dom结构特别复杂,或者添加的元素非常复杂,则代码会变得非常复杂且阅读性低。

很难达到组件化页面

JQuery 时代的代码大部分情况下是面条代码,耦合严重

性能损耗

损耗浏览器资源

新:Vue.js

数据与视图分离

Vue则是通过Vue对象将数据和View完全分离开来了。对数据进行操作不再需要引用相应的DOM对象,可以说数据和View是分离的,他们通过Vue对象这个vm实现相互的绑定。这就是传说中的MVVM。

数据双向绑定

这也就是vue.js最大的优点,通过MVVM思想实现数据的双向绑定,让开发者不用再操作dom对象,有更多的时间去思考业务逻辑。

灵活的组件化

Vue.js通过组件,把一个单页应用中的各种模块拆分到一个一个单独的组件中,我们只要先在父级应用中写好各种组件标签,并且在组件标签中写好要传入组件的参数,然后再分别写好各种组件的实现,然后整个应用就算做完了。

虚拟DOM,运行更快

Virtual DOM,是一种可以预先通过JavaScript进行各种计算,把最终的DOM操作计算出来并优化,由于这个DOM操作属于预处理操作,并没有真实的操作DOM,所以叫做虚拟DOM

4.技术点整理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TcVq9AEc-1679370213961)(笔记图片/image-20230306112212557.png)]

5.学习需要掌握的知识点

轻量级的框架

能够自动追踪依赖的模板表达式和计算属性,提供 MVVM 数据绑定和一个可组合的组件系统,具有简单、灵活的 API,使读者更加容易理解,能够更快上手。

双向数据绑定

声明式渲染是数据双向绑定的主要体现,同样也是 Vue.js 的核心,它允许采用简洁的模板语法将数据声明式渲染整合进 DOM。

客户端路由

Vue-router 是 Vue.js 官方的路由插件,与 Vue.js 深度集成,用于构建单页面应用。Vue 单页面应用是基于路由和组件的,路由用于设定访问路径,并将路径和组件映射起来

指令

Vue.js 与页面进行交互,主要就是通过内置指令来完成的,指令的作用是当其表达式的值改变时相应地将某些行为应用到 DOM 上。

组件化

可随时引用,通过传入参数实现不同的页面,可子父引用。

状态管理

状态管理实际就是一个单向的数据流,State 驱动 View 的渲染,而用户对 View 进行操作产生 Action,使 State 产生变化,从而使 View 重新渲染,形成一个单独的组件。

2. 搭建Vue2.0项目

1. npm、cnpm node环境搭建vue脚手架

1. 安装node.js环境

1.进入官网

https://nodejs.org/en/

2.安装msi,安装目录到C盘

安装好后,使用cmd执行 node- v npm -v看看是否都输出了版本号

3.在除C盘外创建一个nodejsFile文件夹,创建两个文件夹 node_global和node_cache,然后运行以下命令

npm config set prefix "D:\Program Files\nodejs\node_global"
npm config set cache "D:\Program Files\nodejs\node_cache"

4.检查当前系统变量中,path路径有没有叫C:\ProgramFiles\nodejs\node_modules

如果有,创建一个同名路径文件夹在C盘之外的盘符,如果没有就不用管了

  1. 在path变量中配置你的C:\Program Files\nodejs\node_modules路径

2. 安装淘宝镜像 cnpm

功能:和npm一样,npm是从海外镜像仓库下载,cnmp 是从阿里淘宝镜像仓库下载

npm install -g cnpm --registry=https://registry.npm.taobao.org

安装完成使用:cnpm -v 查看版本

3.安装webpack

npm install webpack -g

安装完成使用:npm webpack -v 查看版本

4. 下载vue脚手架

1.下载脚手架资源

cnpm install -g vue-cli@2.x

2.去到你的gloab目录查看是否有vue开头的文件

在这里插入图片描述

  1. 到别的文件夹下创建一个空的文件夹,在文件夹中按住shift+鼠标右键,点击在此处打开pwershell窗口
  1. 打开窗口输入:vue init webpack

5.初始化构建vue脚手架

在这里插入图片描述
在这里插入图片描述

6.运行vue项目

在项目根目录下按住shift+鼠标右键,点击在此处打开pwershell窗口,执行 npm run dev

3. 使用VSCode构建Vue项目

下载VsCode

https://code.visualstudio.com/

组件下载

在这里插入图片描述
在这里插入图片描述

创建vue项目

  1. 创建一个空的项目文件夹
  2. 使用vsCode打开这个文件夹
  3. 设置vsCode语言:ctrl+shift+P 输入指令:Display language 先选择英文重启后再选择中文再重启就好了
  4. 打开终端
vue init webpack

会出现错误:not promite 。。。。 vsCode终端控制台没有系统写入权限

使用本机自带的cmd窗口使用管理员权限启动

将目录跳转至项目路径再执行vue init webpack指令

5.启动项目

npm run dev

在这里插入图片描述

6.退出运行

ctrl+c

4. 编写第一个vue文件

<!-- Dom页面 -->
<template>
	<!-- 所有的页面元素都要卸载div之内 -->
  <div id='UserIndex'>
    
  </div>
</template>

<!-- 组件js -->
<script>
export default {
    name:'UserIndex',
    data(){

    }
}
</script>

<!-- CSS代码 -->
<style scoped>

</style>

使用VSCode创建一个自定义代码片段

文件–》首选项—》配置用户代码片段

{
	"Print to console": {
		"prefix": "myvue",// 代码段名称
		"body": [ //代码内容
			"<!-- Dom页面 -->",
			"<template>",
			"<div id=''>",
			"",
			"</div>",
			"</template>",
			"",
			"<!-- 组件js -->",
			"<script>",
			"export default {",
			"name:'',",
				"data(){",
				"",
				"}",
			"}",
			"</script>",
			"",
			"<!-- CSS代码 -->",
			"<style scoped>",
			"",
			"</style>"
		],
		"description": "myvue"
	}
}

5.App.vue文件

作用:vue项目首页,可以编写全局项目中公共的样式

注意:一般如果项目集成了路由功能,app.vue只会写一个路由标签

<template>
  <div id="app">
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>

<style>
#app {
  
}
</style>

6.main.js-主入口文件

作用:配置通用组件的引入、vue通用配置

import Vue from 'vue'
import App from './App'
import router from './router'

Vue.config.productionTip = false

/* eslint-disable no-new */
// 创建vue,绑定主视图
// 脚手架项目中vue实例只会有一个,存在main.js中
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

vue实例

每个 Vue.js 应用都是通过构造函数 Vue 创建一个 Vue 的根实例 启动的

在这里插入图片描述

7. Vue组件的生命周期(vue2.0)

1. 组件创建阶段-create

在这里插入图片描述

  1. 实例化组件
    1. beforeCreate 创建前
  2. 开启数据监听
  3. 初始化vue内部方法
    1. created 创建完成

vue中使用钩子函数

<template>
  <div class="hello">
    123
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data () {
    return {
      
    }
  },
  //创建前的钩子
  beforeCreate(){
     console.dir("beforeCreate");
  },
  //创建后
  created(){
    console.dir("created");
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

2.组件渲染阶段-mount

在这里插入图片描述

  1. vue选择渲染模板,是要使用vue组件的方式渲染还是只是渲染部分html

    ​ 1.beforeMount - dom元素渲染之前

  2. 开始渲染

    1. mounted - dom挂载结束
<template>
  <div class="hello">
    123
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data () {
    return {
      
    }
  },
  //创建前的钩子
  beforeCreate(){
     console.dir("beforeCreate");
  },
  //创建后
  created(){
    console.dir("created");
  },
  //Dom挂载之前
  beforeMount(){
    console.dir("beforeMount");
    
  },
  //dom挂载完成
  mounted(){
    console.dir("mounted");
  }

}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

3.组件运行阶段-数据更新-update

在这里插入图片描述

  1. 监听器会监听所有data值的变化

    ​ 1.beforUpdate - 数据更新之前

  2. 使用VDom手段动态渲染html

    1. updated - 数据渲染完成
<template>
  <div class="hello">
    {{ name }}
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data () {
    return {
       name:"蔡徐坤"
    }
  },
  //创建前的钩子
  beforeCreate(){
     console.dir("beforeCreate");
  },
  //创建后
  created(){
    console.dir("created");
  },
  //Dom挂载之前
  beforeMount(){
    console.dir("beforeMount");
    
  },
  //dom挂载完成
  mounted(){
    console.dir("mounted");
  },
  //数据更新之前
  beforeUpdate(){
    console.dir("beforeUpdate");
  },
  //数据更新完成
  updated(){
    console.dir("updated");
  }

}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

4.组件销毁阶段-destroy

注意:组件默认情况下不会主动销毁,需要借助v-if指令或者,Vue.$destroy()才会触发vue的销毁流程

在这里插入图片描述

  1. 组件是否进入销毁流程(v-if指令或者,Vue.$destroy())
    1. beforeDestroy - 销毁之前
  2. 进行销毁 - 组件中所有的data值缓存都会消失、vdom缓存也会清除
    1. destroyed - 销毁结束

8.main.js进行全局配置

#取消 Vue 所有的日志与警告 - 开发不要配,生产环境配
Vue.config.silent = true


#配置是否允许 vue-devtools 检查代码 - 开发不要配,生产环境配
Vue.config.devtools = true 

#指定组件的渲染和观察期间未捕获错误的处理函数-全局异常处理回调
Vue.config.errorHandler = function (err, vm, info){} 

#设置为 false 以阻止 vue 在启动时生成生产提示 - 开发不要配true,生产环境配
Vue.config.productionTip = false


9. Vue语法

1. 插值表达式-文本类型(数值、boolean、字符串、字符、对象中的文本类型)

语法:{{ 数据变量名称 }}

是将vue绑定的数据渲染到视图产生关联,实现双向绑定

<template>
  <div class="hello">
    <h1>大家好我叫:{{ name }}</h1>
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data () {
    return {
       name:"蔡徐坤456"
    }
  }

}
</script>

v-once指令

编写位置:插值表达式存在的开始标签中

作用:让插值表达式里的值不会根据data的变化而渲染,永远保持第一次加载的值

<template>
  <div class="hello">
    <h2>{{ name }}</h2>// 蔡徐坤123
    <h2 v-once>大家好我叫:{{ name }}</h2> // 蔡徐坤
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data () {
    return {
       name:"蔡徐坤" // 蔡徐坤123
    }
  }

}
</script>

2.动态插入HTML文本

注意:{{ XXX }}解析的过程只会按照纯文本方式解析,如果要解析html代码段加载到dom中,需要使用v-html指令

v-html指令

<template>
  <div class="hello">
    <!-- 加载html是以纯文本的方式加载 -->
    <!-- <h2>{{ person.myhtml }}</h2> -->
    <!-- 将person.myhtml中的html代码加载到当前标签的子标签中 -->
    <h2 v-html="person.myhtml"></h2> // XXX.html("xxx")
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data () {
    return {
       person:{
         name:"蔡徐坤",
         myhtml:"<span>123</span>"
       }
    }
  }

}
</script>

3.标签属性值动态绑定(重点经常使用)

注意:title={{ xxxx }}不行,插值表达式不能使用在属性值以及属性名称上,标签位置上都不能使用插值表达式

那如果需要动态绑定一个数据给标签的属性值怎么办?就要使用v-bind指令

v-bind指令

<template>
  <div class="hello">
    <h1 v-bind:title="person.title" >欢迎访问网站</h1>
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data () {
    return {
       person:{
         name:"蔡徐坤",
         title:"点击给我充值50块!"
       }
    }
  }

}
</script>

v-bind指令可以简写为":"

 <h1 :title="person.title" >欢迎访问网站</h1>

4.动态绑定表达式

当点击时动态绑定一段js代码

借助v-bind来实现

<template>
  <div class="hello">
    <h1 :οnclick="person.text" >欢迎访问网站</h1>
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data () {
    return {
       person:{
          //表达式字符串
          text:"javascript:var c=0;alert(c)"
       }
    }
  }

}
</script>

5.vue指令

编写的位置:开始标签中在标签的属性位置编写

1. v-once(不可再更新)

2.v-bind(动态绑定属性值)

3.v-html(动态添加子元素解析html)

4.v-on(事件绑定)

复杂写法:

<template>
  <div class="hello">
    <!-- 点击h1标签跳转到百度首页 -->
    <h1 v-on:click.prevent="toBaidu(1)" >欢迎访问网站</h1>
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data () {
    return {
       person:{
          //表达式字符串
          text:"color:red"
       }
    }
  },
  //当前组件的所有方法
  methods:{
    //跳转到百度
    toBaidu(a){ // toBaidu:function(){}
      console.dir(a);
      location.href = "https://www.baidu.com"
    }
  }

}
</script>

简单写法:v-on用@替代

如:当点击时触发函数 @click=“函数”

<template>
  <div class="hello">
    <!-- 点击h1标签跳转到百度首页 -->
    <h1 @dblclick="toBaidu(1)" >欢迎访问网站</h1>
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data () {
    return {
       person:{
          //表达式字符串
          text:"color:red"
       }
    }
  },
  //当前组件的所有方法
  methods:{
    //跳转到百度
    toBaidu(a){ // toBaidu:function(){}
      console.dir(a);
      //location.href = "https://www.baidu.com"
    },
      ...
    aa(){
       this.toBaidu();// this调用别的方法
       this.person.text = "123"; // this访问data值
	}
  }

}
</script>
键盘输入-实现事件触发

敲击回车,实现方法调用

<template>
  <div class="hello">
    <!-- 键盘键入回车就跳转到百度首页 -->
    <h1>欢迎访问网站</h1>
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data () {
    return {
       person:{
          //表达式字符串
          text:"color:red"
       }
    }
  },
  mounted(){//dom渲染完成
    //添加一个监听键盘操作的监听器
    window.addEventListener('keydown', this.mykey);
  },
  //当前组件的所有方法
  methods:{
    //绑定到监听键盘输入的回调方法
    mykey(param){
      if(param.keyCode == 13){// 13 代表敲击回车
        this.toBaidu();
      }
    },
    //跳转到百度
    toBaidu(){ // toBaidu:function(){}
      location.href = "https://www.baidu.com"
    }
  }

}
</script>

js中所有keycode列表

https://blog.csdn.net/fghyibib/article/details/120670221?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-1-120670221-blog-122497397.pc_relevant_multi_platform_whitelistv3&spm=1001.2101.3001.4242.2&utm_relevant_index=4

5.v-if 、v-show

v-if:
true: 标签或者组件被挂载
false:标签或者组件删除或销毁

v-show: 通过display样式控制组件显示隐藏
true: 标签或者组件 - 显示状态
false:标签或者组件 - 被隐藏

<template>
  <div class="hello">
    <!-- 
      v-if: 
        true: 标签或者组件被挂载
        false:标签或者组件删除或销毁
     -->
    <h1 v-if="isOk">欢迎访问网站</h1>
     <!-- 
      v-show: 通过display样式控制组件显示隐藏
        true: 标签或者组件 - 显示状态
        false:标签或者组件 - 被隐藏
     -->
    <h1 v-show="isOk">欢迎访问网站2</h1>
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data () {
    return {
       isOk:true
    }
  },
  mounted(){//dom渲染完成
   
  },
  //当前组件的所有方法
  methods:{
    
  }

}
</script>
v-if挂载过程

当v-if值为true时:组件会进入创建阶段—渲染阶段

​ 如果父组件加载子组件时,子组件被v-if=“false” 描述时,子组件是不会被加载

当v-if值为false是:组件会进入销毁阶段

v-show挂载过程

当v-show值为true时:组件被显示-不会调用生命周期钩子

​ 如果父组件加载子组件时,子组件被v-show=“false” 描述时,子组件会加载但是不显示而已

当v-show值为false是:组件被隐藏-不会调用生命周期钩子

v-if根据boolean控制组件加载,v-show根据boolean控制组件显示隐藏不管值为true还是false都会被提前加载

6.v-else\v-else-if

多条件判断指令

注意:v-if v-els-if v-else要注意编写的顺序和数量,v-else只能有一个,v-else-if可以有多个

注意标签之间的顺序,不要有间隔

<Test1 v-if="isOk"></Test1> // 独立的判断
<h1 v-if="name=='鸡仔'">123</h1> //2 行 一组判断逻辑
<Test2 v-else></Test2>

7.v-for-有序列表的遍历 循环指令

v-for=“(循环中的每个对象,循环遍历的下标) in 要循环的集合数组”

​ 简写-只取出集合中的对象: v-for=“循环中的每个对象 in 要循环的集合数组”

循环中必填参数

​ key:描述循环的标签是独一无二的,只要绑定一个唯一值属性即可,提供给VDom更新元素

<template>
  <div class="hello">
    
    <table>
      <tr>
        <th>编号</th>
        <th>姓名</th>
        <th>年龄</th>
      </tr>
      <!-- 
        v-for="(循环中的每个对象,循环遍历的下标) in 要循环的集合数组"
      -->
      <tr v-for="(item,index) in userList" :key="index">
        <!-- 循环中插入的数据就使用item对象访问属性值用插值表达式输出 -->
        <td>{{item.id}}</td>
        <td>{{item.name}}</td>
        <td>{{item.age}}</td>
      </tr>
    </table>

  </div>
</template>

<script>
//引入组件
import Test1 from './Test.vue';
import Test2 from './Test2.vue';

export default {
  name: 'HelloWorld',
  //注册组件
  components:{Test1,Test2},
  data () {
    return {
       isOk:false,
       name:"鸡仔",
       userList:[
        {
          name:"蔡徐坤",
          age:18,
          id:101
        },
        {
          name:"小鸡仔",
          age:19,
          id:102
        }
       ]
    }
  },
  mounted(){//dom渲染完成
   
  },
  //当前组件的所有方法
  methods:{
    
  }

}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

8.v-for - 遍历map\对象

v-for=“(对象的属性值,对象的属性名称,属性的序号) in 要迭代对象” :key=“唯一值”

<template>
  <div class="hello">
    <!-- v-for="(对象的属性值,对象的属性名称,属性的序号) in 要迭代对象" :key="唯一值" -->
    <h1 v-for="(value,key,index) in userData" :key="index">
      [{{index}}]{{key}}====={{value}}
    </h1>
    

  </div>
</template>

<script>
//引入组件
import Test1 from './Test.vue';
import Test2 from './Test2.vue';

export default {
  name: 'HelloWorld',
  //注册组件
  components:{Test1,Test2},
  data () {
    return {
       isOk:false,
       name:"鸡仔",
       userData:{
         name:"ikun",
         age:0,
         id:101
       }
    }
  },
  mounted(){//dom渲染完成
   
  },
  //当前组件的所有方法
  methods:{
    
  }

}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

9.v-model 表单数据绑定

在传统H5开发的方式下,表单的值一般是用value属性控制,但是进过测试动态绑定表单标签的value属性无法实现表单值的变化,这时我们需要使用v-model指令实现表单数据的动态绑定

1. v-model在文本域中的使用方法

<template>
  <div class="hello">
      <input v-model="name"/>
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data(){
    return {
      name:null
    }
  }

}
</script>
<style scoped>
</style>

注意:使用vue后,表单元素绑定数据就要使用v-model而不要再使用value属性了

1.v-model.lazy

效果:当填写完成,选中效果移除之后数据才更新

<input v-model.lazy="name"/>
2. v-model.number

效果:在填写文本时,只能填写数字

注意:只有填写文字是数字开头才有用,而且从数字开头截取字符直到出现第一个非数字位置结束,如:1a2b ===> 1

<input v-model.number="name"/>

推荐如果是纯数字校验,使用type=“number”

<input type="number" v-model.number="name"/>
v-model.trim

去除前后空格的方式

<input v-model.trim="name"/>

2. v-model在选择器中的使用方法

<!-- 如果需要回填自动选中选项,只要改变v-model绑定的数据值就ok -->
      <select v-model="name">
        <!-- 描述属性是数值类型时,需要添加v-bind -->
        <option :value="1">昆明</option>
        <!-- 描述属性是boolean类型时,需要添加v-bind -->
        <option :value="true">临沧</option>
        <option value="3">蒙自</option>
      </select>

3. v-model 在单选和复选框中的使用方法

单选框
<template>
  <div class="hello">
      <input type="radio" name="sex" :value="1" v-model="sexCode"/>男
      <input type="radio" name="sex" :value="2" v-model="sexCode"/>女
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data(){
    return {
      sexCode:null
    }
  }

}
</script>
<style scoped>
</style>

复选框
<template>
  <div class="hello">
      <input type="checkbox" name="like" :value="1" v-model="likeCode"/>吃鸡
      <input type="checkbox" name="like" :value="2" v-model="likeCode"/>lol
      <input type="checkbox" name="like" :value="3" v-model="likeCode"/>王者别嚣张
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data(){
    return {
      likeCode:[]// checkbox情况下,初始化值一定是要一个空数组
    }
  }

}
</script>
<style scoped>
</style>

4. v-model使用在文本域中

<template>
  <div class="hello">
      <textarea v-model="name"></textarea>
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data(){
    return {
      name:null
    }
  }

}
</script>
<style scoped>
</style>

10.过滤器

目的:可以改写插值表达式的显示内容

<template>
  <div class="hello">
    <!-- userData.name值nameFilter过滤器中 -->
    <!-- 过滤器可以改写插值表达式的内容 -->
    <h1>{{ userData.name | nameFilter | nameFilter2 }}</h1>
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data () {
    return {
       isOk:false,
       name:"鸡仔",
       userData:{
         name:"ikun",
         age:0,
         id:101
       }
    }
  },
  //过滤器
  filters:{
      //自定义过滤器
      nameFilter:function(value){
          console.dir(value);

          //要定义返回值
          return "欢迎管理员:"+value+",登录系统";
      },
      nameFilter2:function(value){
        console.dir(value);
        return value+"!!!!!!"
      }
  }

}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

v-bind指令也能配合过滤器使用

<h1 :title="userData.name | nameFilter">点击查看用户信息</h1>

vue3.0已经弃用过滤器

11. 计算属性

计算属性使用场景:

和过滤器比较:

​ 过滤器:参数只能是插值表达式中|之前的值注入到过滤器的参数中,过滤器无法访问data绑定的数据

​ 计算属性:参数可以是在计算属性调用时的实参也可以访问data绑定的数据(this访问)

使用计算属性-无参的方法

<h1>{{ nameComputed }}</h1>
//计算属性
  computed:{
      //自定义计算属性
      nameComputed:function(){
          return this.userData.name.split('').reverse().join('');
      }
  }

使用计算属性-可以传递参数的方法

<h1>{{ nameComputed("1",1,3) }}</h1>
//计算属性
  computed:{
      //自定义计算属性
      nameComputed(){
         return function(value,value2,value3){
            console.dir(value);
            return this.userData.name.split('').reverse().join('');
         }
      }
  }

method方法能不能使用到插值表达式中

是可以的,但是推荐使用计算属性完成

method和computed的区别

计算属性:

​ 计算属性会使用浏览器缓存进行数据的存储和计算

​ 计算属性可以根据行为是读取还是参数赋值区分出get和set两种方法模式

mycomputed:{
        get:function(){// 无参调用计算属性时触发
          console.dir("get");
          return "get";
        },
        set:function(){// 有参调用计算属性触发
          console.dir("set");
          return "set";
        }
      }

而方法每次调用都需要经过函数执行的读写,没有任何缓存的实现,所以性能较差,当开发目的只是为了改变插值表达式的值内容的情景时,推荐使用计算属性完成

12.监听器

作用:监听data绑定数据的变化

注意:要监听的数据如果保存在对象中话写法有所区别

<template>
  <div class="hello">
     <h2>{{ userData.age }}</h2>
     <button @click="userData.age +=1">点击我+1!</button>
     <button @click="userData.age -=1">点击我-1!</button>

     <h2>{{ aa }}</h2>
     <button @click="aa +=1">点击我+1!</button>
     <button @click="aa -=1">点击我-1!</button>
  </div>
</template>

<script>

export default {
  name: 'HelloWorld',
  data () {
    return {
       isOk:false,
       name:"鸡仔",
       aa:0,
       userData:{
         name:"ikun",
         age:0,
         id:101
       }
    }
  },
  methods:{// 普通方法就像js中的函数 function
    say(){
      return "123456";
    }
  },
  watch:{//监听器- 可以监听data绑定数据的变化
    // data绑定数据的名称(新变化的值,变化之前的值)
    aa(newValue,oldValue){
        console.dir(newValue+"-----"+oldValue);
    },
    //要监听的数据是存在对象中的
    "userData.age"(newVal,oldVal){
        console.dir(newVal+"-----"+oldVal);
    }

  }

}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

深度监听

多组件共用data值的时候会使用

"userData.data.data.age":{
      immediate:true,// 深度监听立即执行
      deep: true,//  开启深度监听
      handler(newVal,oldVal){
        console.dir(newVal+"-----"+oldVal);
      }
}

在昨天的学生信息列表功能下实现前端的:添加、编辑功能

  1. 添加功能:
    1. 在表格上方会有一个添加按钮
    2. 点击添加按钮弹出一个div,里面有学生信息添加内容的表单以及保存、重置表单按钮
    3. 填写完数据点击保存,弹窗关闭,表格数据刷新
  2. 编辑功能
    1. 表格中多一列操作列
    2. 操作列对应每一行中有编辑按钮
    3. 点击编辑弹出编辑div,里面有学生信息编辑内容的表单以及保存编辑
    4. 填写完数据点击保存,弹窗关闭,表格数据刷新
  3. 实现添加表单和编辑表单公用一个div和表单内容,通过判断实现

13. 动态样式绑定方法

动态修改class属性的方法实现样式变化

1.对象语法

<template>
  <div class="hello">
    <!-- isUse为true则class属性值为class="div1" 为false class=""  -->
    <div :class="{ div1: isUse , hide : isUse2}"></div>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      isUse: false,
      isUse2:false
    };
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.div1 {
  width: 100px;
  height: 100px;
  background-color: red;
}

.div2 {
  width: 100px;
  height: 100px;
  background-color: yellow;
}

.hide{
    display: none;
}

</style>


2. 数据绑定实现class属性变化

<template>
  <div class="hello">
    <div :class="myDivClass"></div>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      myDivClass:{
        div1:true,// 需要添加div1 值
        hide:false// hide值不添加
      }
    };
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.div1 {
  width: 100px;
  height: 100px;
  background-color: red;
}

.div2 {
  width: 100px;
  height: 100px;
  background-color: yellow;
}

.hide{
    display: none;
}

</style>

3. 通过数组的方式控制class属性值内容

<template>
  <div class="hello">
    <div :class="[activeDiv1,activeHid]"></div>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      activeDiv1:'div1', //属性值是样式名称
      activeHid:'hide'
    };
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.div1 {
  width: 100px;
  height: 100px;
  background-color: red;
}

.div2 {
  width: 100px;
  height: 100px;
  background-color: yellow;
}

.hide{
    display: none;
}

</style>

数组中可以使用表达式完成样式的选择

<template>
  <div class="hello">
    <!-- 数组中可以使用表达式完成样式的选择 -->
    <div :class="[isUser==true?activeDiv1:'xx',activeHid]"></div>
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  data() {
    return {
      activeDiv1:'div1', //属性值是样式名称
      activeHid:'hide',
      isUser:false
    };
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.div1 {
  width: 100px;
  height: 100px;
  background-color: red;
}

.div2 {
  width: 100px;
  height: 100px;
  background-color: yellow;
}

.hide{
    display: none;
}

</style>

动态修改内联样式style属性的方法

1.嵌入对象的方法

<template>
  <div class="hello">
    <!-- 样式值实现动态绑定 -->
    <div :style="{color:fontColor,backgroundColor:bgColor,with:'100px',height:'100px'}"></div>
    <input v-model="bgColor" />
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  data() {
    return {
        fontColor:'red',
        bgColor:'yellow'
    };
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

2. 数据绑定style属性方法

<template>
  <div class="hello">
    <!-- 样式值实现动态绑定 -->
    <div :style="myStyle"></div>

    <input v-model="myStyle.backgroundColor" />
  </div>
</template>

<script>
export default {
  name: "HelloWorld",
  data() {
    return {
        myStyle:{// 需要绑定到style属性中的对象要求:属性名称是样式名称,属性值是样式值
            color:'red',
            backgroundColor:'yellow',
            width:'100px',
            height:'100px'
        }
    };
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

14.组件开发方法

1.引入使用组件方法

子组件代码

<!-- Dom页面 -->
<template>
  <div id="TestIndex">
    测试页面1
  </div>
</template>

<!-- 组件js -->
<script>
export default {
  name: "TestIndex",
  data() {
    return{

    }
  },
};
</script>

<!-- CSS代码 -->
<style scoped></style>

父组件代码

<template>
  <div class="hello">
    <!-- 3.通过标签的方式引入组件,标签名称就是组件名称 -->
    <Test />
  </div>
</template>

<script>
//1. 导入要使用的组件  @代表的就是src目录路径,有点像classpath
import Test from '@/components/Test.vue';

export default {
  name: "HelloWorld",
  components:{Test},// 2.注册声明组件使用
  data() {
    return {
        
    };
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

2.子组件接收父组件数据

子组件要定义能接收的数据有些什么(组件参数)

props属性定义

注意:子父组件值传递是值的拷贝,不会传递地址

子组件写法

<!-- Dom页面 -->
<template>
  <div id="TestIndex">
    测试页面1{{ name }}
    <input v-model="name">
  </div>
</template>

<!-- 组件js -->
<script>
export default {
  name: "TestIndex",
  props:{//组件接收参数定义 使用props参数值的方式和使用data绑定数据的方法一样
    // 注意不要和data中的数据名称重复
     name:{
       type:String,// String:字符串字符类型 Number:数值类型 Array:集合数组类型 Object:对象、map类型
       default:'只因你太美' //默认值
     },
     age:{
       type:Number,
       default:18
     }
  },
  watch:{
    name:function(newV,oldV){
      console.dir("监听:"+newV+"---"+oldV);
    }
  },
  data() {
    return{
        sonName:this.name //访问props参数方法和访问data值方法一致
    }
  },
  methods:{
    aa(){
      console.dir(this.name);//访问props参数方法和访问data值方法一致
    }
  }
};
</script>

<!-- CSS代码 -->
<style scoped></style>

父组件传递方法

<template>
  <div class="hello">
    <!-- 3.通过标签的方式引入组件,标签名称就是组件名称 -->
    <!-- 给子组件props参数传值是通过标签属性传递的 -->
    <Test :name="fatherName" :age="12" />
  </div>
</template>

<script>
//1. 导入要使用的组件  @代表的就是src目录路径,有点像classpath
import Test from '@/components/Test.vue';

export default {
  name: "HelloWorld",
  components:{Test},// 2.注册声明组件使用
  data() {
    return {
        fatherName:"蔡徐坤"
    };
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>

</style>

当子组件点击关闭按钮时,父组件要接收关闭事件的回调

需要子组件通知父组件,有事情发生,让父组件能够接收这个消息

3. 子组件与父组件回调方法

能实现子组件将数据传递到父组件

案例:点击子组件的关闭按钮,实现父组件div隐藏

子组件代码

<!-- Dom页面 -->
<template>
  <div id="TestIndex">
      <button @click="sonClose">关闭</button>
  </div>
</template>

<!-- 组件js -->
<script>
export default {
  name: "TestIndex",
  data() {
    return{
        
    }
  },
  methods:{
    sonClose(){//子组件点击了关闭按钮
      //让父组件接收到我的这个信息
      // 如果需要传递参数,接收时一定要按照传递时的顺序取参数
      this.$emit("sClose","cxk",123);// 封装了一个方法名叫sClose的回调函数通知父组件
    }
  }
};
</script>

<!-- CSS代码 -->
<style scoped></style>

父组件代码

<template>
  <div class="hello">
      
        <div class="myDiv" v-if="isShow">
            <!-- 回调函数接收的方法不要定义参数列表 -->
            <Test @sClose="fatherFunction"/>
        </div>

  </div>
</template>

<script>
//1. 导入要使用的组件  @代表的就是src目录路径,有点像classpath
import Test from '@/components/Test.vue';

export default {
  name: "HelloWorld",
  components:{Test},// 2.注册声明组件使用
  data() {
    return {
        isShow:true
    };
  },
  methods:{
    //父组件接收子组件回调的方法
    fatherFunction(param,param2){
        console.dir(param);
        console.dir(param2);
        this.isShow = false;
    }
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.myDiv{
    width: 200px;
    height: 200px;
    background-color: aqua;
}
</style>

  1. 定义一个子组件,功能是:通过父组件传递的列表数据实现一个动态下拉框
  2. 当下拉框选中数据时,要回调一个时间给父组件(change\selected)
  3. 实现下拉框清空功能,点击清空清空select选择的内容,然后回调一个事件给父组件(clear\qingkong)

在这里插入图片描述

4.子组件定义好后,父组件引入组件,试用是否正常

15. 路由

1. 路由是什么

2. 路由的三个对象

route:首先它是个单数,译为路由,即我们可以理解为单个路由或者某一个路由;( 单个路由信息 )

routes:它是个复数,表示多个的集合才能为复数;即我们可以理解为多个路由的集合,JS中表示多种不同状态的集合的形式只有数组和对象两种,事实上官方定义routes是一个数组;所以我们记住了,routes表示多个数组的集合;(整个项目中的所有路由信息)

router:译为路由器,上面都是路由,这个是路由器,我们可以理解为一个容器包含上述两个或者说它是一个管理者,负责管理上述两个;举个常见的场景的例子:当用户在页面上点击按钮的时候,这个时候router就会去routes中去查找route,就是说路由器会去路由集合中找对应的路由;(对象,可以实现路由的多种功能跳转)

3.如何配置路由

什么地址可以访问哪个组件,描述一下路由信息

  1. 编写组件页面

​ 2.打开路由配置文件

在这里插入图片描述

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
//1. 导入需要配置路由的组件
import Test2 from '@/components/Test2.vue';

Vue.use(Router)

export default new Router({
  // 所有路由信息-集合
  routes: [// 第一个路由记录就是欢迎页
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld,
      meta:{
        index:0,
        name:"首页"
      }
    },
    {// 2.编写路由
      path: '/test2',// 访问路径
      name: 'Test2', //路由组件名称
      component: Test2, //关联组件
      meta:{
        index:1, // 组件顺序-按照组件关系写
        name:"测试页面2" // 路由组件名称-中文描述-提供面包屑使用
      }
    }
  ]
})

改变路由访问的方法

export default new Router({
  mode: 'history',// 路由地址前面就不会有/#/

4. 路由跳转方法

1. router-link标签

<!-- 效果类似a标签 -->
        <!-- <a href="/test2">XXXX</a> -->
        <router-link to="/test2">跳转到test2页面</router-link>

2. $router对象

puish方法- 是会把路由跳转的记录添加到浏览器的缓存记录中的,就可以使用浏览器的前进和后退功能

replace方法-则不会将访问的数据添加到记录中

1.push方法- 直接传递路由地址字符串
<template>
  <div class="hello">
        <button @click="doRouter">点击跳转</button>
  </div>
</template>

<script>

export default {
  name: "HelloWorld",
  data() {
    return {
        
    };
  },
  methods:{
    //路由跳转方法
    doRouter(){
       this.$router.push('/test2');
    }
  }
};
</script>

2.push方法-传递一个路由信息对象
<template>
  <div class="hello">
        <button @click="doRouter">点击跳转</button>
  </div>
</template>

<script>

export default {
  name: "HelloWorld",
  data() {
    return {
        routeData:{
          path:'/test2'
        }
    };
  },
  methods:{
    //路由跳转方法
    doRouter(){
       this.$router.push(this.routeData);
    }
  }
};
</script>
3.push-传递的路由信息对象-跳转的页面是通过name确定
<template>
  <div class="hello">
        <button @click="doRouter">点击跳转</button>
  </div>
</template>

<script>

export default {
  name: "HelloWorld",
  data() {
    return {
        routeData:{
          name:"Test2" // 路由定义的index.js中定义路由的name值
        }
    };
  },
  methods:{
    //路由跳转方法
    doRouter(){
       this.$router.push(this.routeData);
    }
  }
};
</script>
4.replcae方法

和push用法相同

// 字符串
this.$router.replace('/home/first')
// 对象
this.$router.replace({ path: '/home/first' })
// 命名的路由
this.$router.replace({ name: 'home', params: { userId: wise }})

5. go方法
//前进一步 相当于history.forward()
this.$router.go(1) 
、
//后退一步 相当于history.back()
this.$router.go(-1) 

this.$router.go(10) 

3. 嵌套子路由

使用场景: 企业管理系统后端,左侧菜单右侧组件刷新的界面

主页:

<!-- Dom页面 -->
<template>
  <div id="Main">

        <h1>主页</h1>
        <router-link to="/user">用户管理</router-link>
        <router-link to="/role">角色管理</router-link>
        <!-- 路由切换视图标签 -->
        <router-view />    
  </div>
</template>

<!-- 组件js -->
<script>
export default {
  name: "Main",
  data() {
    return {};
  }
};
</script>

<!-- CSS代码 -->
<style scoped></style>

路由配置

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Main from '@/components/main'
//1. 引入组件
import User from '@/components/user'
import Role from '@/components/role'

Vue.use(Router)

export default new Router({
  mode: 'history',// 路由地址前面就不会有/#/
  // 所有路由信息-集合
  routes: [// 第一个路由记录就是欢迎页
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld,
      meta:{
        index:0,
        name:"登录页面"
      }
    },
    {
      path: '/main',
      name: 'Main',
      component: Main,
      meta:{
        index:1,
        name:"首页"
      },
      children:[// 子路由!!!!!!!
        {
          path: '/user',
          name: 'User',
          component: User,
          meta:{
            index:1-1,
            name:"用户管理"
          }
        },
        {
          path: '/role',
          name: 'Role',
          component: Role,
          meta:{
            index:1-2,
            name:"角色管理"
          }
        }
      ]
    }
    
  ]
})

5.路由传参

1. 在路由路径上拼接参数- 刷新页面参数也不会丢失

路由配置文件中,在path属性上声明会出现参数的位置

{
      path: '/:id', // 在/ 路径之后 会传递一个 名字叫id的参数
      name: 'HelloWorld',
      component: HelloWorld,
      meta:{
        index:0,
        name:"登录页面"
      }
    },

调用路由跳转是传递参数

注意:只能传递简单的字符串和数值、boolean类型,不能传递对象

this.$router.push({ path:`/main/${this.param}`});

目标路由组件中获取参数

<!-- Dom页面 -->
<template>
  <div id="Main">

        <h1>主页</h1>
        <h1>{{ $route.params.id }}</h1>
  </div>
</template>

2.在调用路由方法时,添加params属性传递参数-刷新页面参数就丢失

路由配置文件就不用修改了

调用路由跳转方法

该方法是支持对象传递的

// 想要使用params传递参数,路由跳转的方法必须使用name指定路由页面才行
       this.$router.push({ name:"Main",params:this.param});

3.在调用路由方法是,添加query属性传递参数-刷新页面也不会丢失参数

路由配置文件就不用修改了

调用路由跳转方法

该方法是支持对象传递的

this.$router.push({ path:"/main",query:this.param});

路由目标页面取参数,要通过query参数取得

this.loginUser = this.$route.query.name;

总结路由传参3种方法:

1.路径拼接法: 如果面有必须要初始化或者必须传递参数才能使用的场景时在使用

​ 2.params方法:对传递的参数进行加密,但是数据传输是一次性的

​ 3.query方法:对参数没有进行加密,直接暴露在url中

routes对象访问

this.$router.options.routes

能够访问当前项目的所有路由信息

6.Vue路由跳转加载进度条

1. 使用Nprogress

在项目的窗口中执行

cnpm install nprogress

2.main.js中引入组件和样式

import NProgress from 'nprogress' 
import 'nprogress/nprogress.css'// nprogress样式文件

3.路由组件钩子函数配置

两个钩子:路由跳转前和跳转后

// 路由的钩子函数是main.js中配置的

// 路由跳转之前
router.beforeEach((to, from , next) => {
    // 开启进度条
    NProgress.start();
    // 这个一定要加,没有next()页面不会跳转的。这部分还不清楚的去翻一下官网就明白了
    next();
});


//当路由跳转结束后
router.afterEach(() => {  
    // 关闭进度条
    NProgress.done()
})


  1. 需要实现一个增删改查分页的表格组件

16. axios组件

作用: 与ajax一样,底层实现就是js-ajax,写法要比之前学习的JQuery、js的ajax都要简单

安装步骤

//1. 在项目窗口中执行
cnpm install axios


main.js中配置axios内容

import axios from 'axios'
Vue.prototype.$axios = axios //全局属性

全局属性的定义方法

在main.js中定义

// 定义全局属性的方法
// Vue.prototype.自定义属性名 = 组件对象
// 属性命名规则:$+属性名
// 在组件中使用全局属性: this.$axios   
Vue.prototype.$axios = axios //全局属性

跨域问题处理、请求服务地址配置

什么是跨域?

出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)

注意: 协议+主机+端口有一个不相同就会出现跨域问题

1.配置BaseUrl,在main.js文件中

axios.defaults.baseURL = '/api'  //关键代码,/api之后替换的就是 http://localhost:8090

2.配置代理,在config文件夹下的index.js文件中的proxyTable字段

module.exports = {
  dev: {

    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: { // 配置到这里!!!!
      '/api': {// 配置了一个静态地址代理
        target:'http://localhost:8090', // 后端服务地址以及端口号
        changeOrigin:true,  // 可以跨域
        pathRewrite:{
          '^/api': ''
        }
      }
    },
  1. main.js 修改 axios全局属性的创建方法
Vue.prototype.$axios = axios.create({
	baseURL:'/api',
	timeout:30000
})

  1. 把项目停止,执行cnpm install ,再启动项目
  1. 测试案例
getData() {
      console.dir(this);
      // 在axios代码中要使用this关键字访问data或者方法等等vue组件内容的话需要定一个别名变量
      let _this = this;
      this.$axios
        .get("goods/goods/getGoodsByID?id=101")
        .then(function(res) {
          _this.resData = res.data;
        })
        .catch(function(error) {
          // 请求失败处理
          console.log(error);
        });
    }

4种请求

GET请求

  1. 参数拼接在url后面
// 直接在 URL 上添加参数 ID=12345
axios.get('/user?ID=12345')
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

  1. 传入一个有params属性的参数
 this.$axios
        .get("goods/goods/getGoodsByID",{
          params:{// 写键值对参数内容
            id:101
          }
        })

POST请求

请求已经将数据封装为json数据发送后端了,所以在后端编写controller方法时,记得要使用@RequestBody注解接收参数

put\delete请求写法和post一致

this.$axios
        .post("goods/goods/testpost",{  // 参数传递的方法和GET不同
          name:"张三",
          price:18.9
        })

批量提交请求方法

需要使用的是axios组件对象的all方法,而以上案例中使用的$axios对象是通过组件对象.create创建的实例

所以我们需要从新定义一个全局的axios组件对象

main.js中定义组件对象全局属性

Vue.prototype.$VueAxios = axios;  // all 再用该对象    新配置的组件对象

Vue.prototype.$axios = axios.create({// get post delete put
	baseURL:'/api',
	timeout:30000
})

批量接口调用方法

getData1() {
       return  this.$axios
        .post("goods/goods/testpost",{
          name:"张三",
          price:18.9
        });
    },
    getData2() {
       return  this.$axios.get("goods/goods/getGoodsByID?id=101");
    },
    //合并提交方法
    getAllData(){
      let _this = this;
      console.dir(this.$axios);
      this.$VueAxios.all([_this.getData1(),_this.getData2()]) // 按照数组顺序调用
      .then(_this.$VueAxios.spread(function (res1, res2) { // 根据调用方法的数量定义接收对应方法返回的数据参数
        // 当所有的方法执行完成且都有返回值之后
          console.dir("请求完成");
          console.dir(acct);
          console.dir(perms);
       }));

    }

请求拦截器

请求拦截器的作用

在axios发送请求到后端之前进行拦截,可以修改请求的参数等内容

写在main.js中

// http request 请求拦截器
axios.interceptors.request.use(config => {
	// 在发送请求之前做些什么
	return config;
}, error => {
	// 对请求错误做些什么
	return Promise.reject(error);
});

响应拦截器

作用:

​ 所有的请求返回响应时都会进入改拦截器

// 响应拦截器
Vue.prototype.$axios.interceptors.response.use(response => {

  console.dir(response);
  if(response.data.code == "9999"){//系统异常
    // 统一错误提示弹窗
  }else if(response.data.code == "-1"){ // 登录会话失效
    // 使用路由返回到登录页面
  }

  return response;
},error => {
  if (error.response) {
   // 返回接口返回的错误信息
   return Promise.reject(error.response.data);
 }
});

17. 子组件自定义v-model

v-model: 只能在表单功能上出现

案例:子组件实现性别单选,v-model实现绑定性别的code值,子父组件修改v-model绑定的子父数据都会改变

子组件写法

<template>
  <div id="Test1">
    <!-- 子组件:性别的单选框 怎么设计和实现v-model -->
    <input type="radio" :value="1" :checked="isManChecked" name="sex" @change="sexChange(1)" />男
    <input type="radio" :value="2" :checked="isWoManChecked" name="sex" @change="sexChange(2)"/>女
  </div>
</template>


<script>
export default {
  name: "Test1",
  props:{
    sexCode:{
        type:Number
    }
  },
  //v-model绑定数据
  model:{
        prop:'sexCode',  // v-model绑定的参数是sexCode字段
        event:'onchange' // v-model数据更新的回调事件叫什么(v-model更改过程是依赖事件)
  },
  watch:{
    sexCode:function(newV,oldV){
        if(newV==1){//男选中
            this.isManChecked = true;
            this.isWoManChecked = false;
        }else{//选中女
            this.isManChecked = false;
            this.isWoManChecked = true;
        }
    }
  },
  data() {
    return {
        isManChecked:false,
        isWoManChecked:false
    };
  },
  methods:{
    sexChange(param){
        this.$emit("onchange",param); // 第二个参数,就是更新父组件v-model绑定数据的值
    }
  }
};
</script>

<!-- CSS代码 -->
<style scoped></style>

父组件

<Test1 v-model="data" />

18.插槽

作用:能够将指定的标签放置在组件的插槽容器中,可以规范组件内容组成也可以灵活配置组件内容

插槽标签

<slot>。。</slot>

插槽-默认插槽

也叫无具名插槽,一般用在父组件快速批量替换子组件默认内容时使用

子组件定义

<template>
  <div id="Test1">
    <div class="div1">
        <!-- 默认插槽写法:<slot> -->
        <slot>默认插槽的文字1</slot> 
    </div>
    <div class="div2">
        <slot>默认插槽的文字2</slot>
    </div>
  </div>
</template>

父组件改变默认插槽方法

<Test1 v-model="sexCode" >
   <!-- 在子组件中添加html代码段就会替换默认插槽信息 -->
   <h1>XXX</h1>
   <h1>XXX222</h1>
</Test1>

在这里插入图片描述

具名插槽

子组件定义

<template>
  <div id="Test1">
    <div class="div1">
        <slot name="one">插槽的文字1</slot>
    </div>
    <div class="div2">
        <slot name="two">插槽的文字2</slot>
    </div>
  </div>
</template>

父组件

<Test1 v-model="sexCode" >
        <!-- 具名插槽赋值方法:template标签 v-slot:插槽的name值 -->
        <template v-slot:one>
         <h1>XXX</h1>
        </template>
      </Test1>

slot属性赋值具名插槽方法

<!-- 具名插槽赋值方法:可以使用在标签上  slot="插槽名称" -->
        <div slot="one">
          <h1>XXX</h1>
        </div>

对象作用域插槽

子组件

<template>
  <div id="Test1">
    <div class="div1">
        <!-- 绑定了一个叫obj的属性在插槽上 -->
        <slot :obj2="objData" :obj="objData">插槽的文字1</slot>
    </div>
  </div>
</template>

<script>
export default {
  name: "Test1",
  data() {
    return {
        objData:{
            name:"张三",
            age:18
        }
    };
  },
  methods:{
  }
};
</script>

父组件

<Test1 v-model="sexCode" >
        <!-- template标签声明v-slot="定义一个变量接收子组件插槽中定义的对象" -->
        <template v-slot="objData">
          <!-- 对象.插槽属性名.插槽属性对象的属性值 -->
          <h1>{{ objData.obj2.name }}</h1>
        </template>
      </Test1>

19. Vuex状态管理

1.安装方法

在项目cmd窗口中执行

cnpm install vuex

创建一个store.js的文件,

在src目录下创建vuex文件夹,在文件夹中创建store.js文件

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
    state:{

    },
    getters:{

    },
    mutations:{

    },
    actions:{
        
    }
});

在main.js中导入组件

//导入vuex组件内容
import Vuex from 'vuex';
import store from './vuex/store'
Vue.use(Vuex);
Vue.prototype.$store = store;


// 修改原有的new Vue构造器
new Vue({
  el: '#app',
  router,
  store, // 添加到全局组件
  components: { App },
  template: '<App/>'
})

使用方法

1. 设置保存数据

在state对象中描述要保存的数据

export default new Vuex.Store({
    state:{// 共享的数据
        count:0
    },

2. 修改数据

1.action - 无参调用方法
actions:{// 操作state里的数据方法
        addCount(){// 每次调用让count数据+1
            this.state.count++;
        },

调用方法

// 调用了vuex中action中的addCount方法,无参调用
        this.$store.dispatch("addCount"); // 字符串的action方法名
2.action - 有参调用方法
// 形参1: vuex对象
// 形参2: 传入的数据(如果要传递多个参数,就封装到对象中---map、集合)
addCount2(obj,param){
    this.state.count += param;
}

调用的方法

this.$store.dispatch("addCount2",123);
3. mutations - 无参调用
mutations:{
        m_addCount(){
            this.state.count++;
        }
    },

调用方法

this.$store.commit("m_addCount");
4.mutations - 有参调用
// 形参1:  state对象 
// 形参2: 传入的数据(如果要传递多个参数,就封装到对象中---map、集合)
m_addCount2(obj,param){
            console.log(obj); // state对象 
            this.state.count += param;
        }

调用方法

this.$store.commit("m_addCount2",123);

3. 获取值

getters

getters:{// 获取值的操作
        getCount(obj){// 参数注入了当前vuex的state对象
            console.dir(obj.count); 
            return obj.count; // $store.getters.getCount
        }
    },

调用方法

this.$store.getters.getCount

mutations和action 方法使用选择

如果需要异步快速执行就使用action方法,如果是需要保证数据读写安全通过等待就使用mutations方法

action方法是会返回promise函数,可以使用then和catch描述方法调用成功或失败的节点

而 mutations方法没有,就只是一个简单的函数调用

推荐使用mutations方法,因为同步安全

20.ElementUI

1. 安装

项目cmd窗口执行

cnpm install element-ui

在main.js中导入el组件内容

//导入elementui
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
Vue.use(ElementUI);

测试el组件能否使用


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神秘的高先生

编写不易,感谢大佬的赏赐

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值