vue.js学习笔记

1、简介

概述:Vue是一款用于构建用户界面的 JavaScript 框架。
	它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。
渐进式:vue可以自底向上逐层的应用,无论是简单还是复杂的界面,Vue 都可以胜任。
	简单应用:只需一个轻量小的核心库
	复杂应用:可以引入各式各样的vue插件
	渐进式就是按需逐渐集成功能
Vue的特点:
	采用组件化模式,提高代码复用率、且让代码更好维护。

1.1、vue和原生js的区别

目标:更少的时间,干更多的活,开发网站速度快
原生js:操纵dom
vue:操纵数据

1.2、库和框架的区别:库是方法的集合,而框架是一套拥有自己规则的语法

vue.js学习笔记_第1张图片

1.3、什么是声明式开发,什么是组件式开发?

声明式开发:无需直接操作DOM
组件式开发:将页面拆分成很多个小组件,重复的直接复用即可,更方便管理

1.4、MVVM模型

vue.js学习笔记_第2张图片

1M:模型(Model):对应data中的数据
2V:视图(View):模板
3VM:视图模型(ViewModel):Vue实例对象//桥梁

1.5、插件安装

1、调试插件:vue.js devtools//谷歌商店下载
2、代码高亮和提示插件:Vue Language Features (Volar)和VueHelper

2、API语法:

绝大多数和vue2相同

0、创建实例语法

1、Vue2:
语法一:
	new Vue({
          el:'#app'//标签,写法一
          data:{
          	 name:'张三'//数据,对象式
     	}
     })
语法二:
	const v = new Vue({
          data(){ ===  data:function(){ //数据,函数式
               return {
                   	name:'张三'//数据,函数式
               }
          })
     v.$mount('#app')//标签,写法二,使用的是原型对象上的方法,更灵活,比如定时几秒后再绑定
2、Vue3:
     Vue.createApp({ // 当前应用实例的选项
           data () { // 书写形式为函数,表示vue实例中需要使用的 数据的变量,必须含有返回值,返回值为对象
             return {
               msg: 'hi world',
               count: 10
             }
           }
     }).mount('#app')
3、Vue.config.productionTip = false//阻止 vue在启动时生成生产提示

1、模板式语法

1、插值语法:{{}}//不支持null和undefined
	例如:<div>{{括号里可以放js表达式}}</div>
		let num = 'hello';
	      <div>{{num.split('').reverse().join('')}}</div>
2、指令语法:
	用于解析标签(标签属性、标签体内容...)
	例如:v-bind:href="xxx"或简写为 :href="xxx",xxx要写js表达式	

2、文本类指令

v-html 和v-text:都写在标签里当做属性
	v-html:识别标签//存在安全性问题,容易导致xss攻击
		不要将v-html用在用户提交的内容上
	v-text:不识别标签
	vue2中使用v-html和v-text会覆盖掉原标签里的内容
	vue3中使用v-html和v-text,标签里有内容的话会警告

3、数据绑定

单向数据绑定://只能从data流向页面
	语法:v-bind:属性名 = "data"
		v-bind:属性名 = "常量"
		v-bind:src="url"
	简写::属性名="data中的变量"
双向数据绑定://不仅可以从data流向页面,也可以从页面流向data
	语法:v-model//收集的是value的值,只能用于有value值的标签,比如input等
	v-model绑定在多选上时,根据类型传值,非数组则为布尔,数组则为选中的
	v-model绑定在下拉菜单上时,显示哪个,值就是哪个

4、事件绑定

1、语法:
	v-on:事件类型="少量的js代码(要求代码是赋值语法)"
	v-on:事件类型="函数名"
	v-on:事件类型="函数名(参数)"
2、简写:
	@事件类型="少量的js代码(要求代码是赋值语法)"
	@事件类型="函数名"
	@事件类型="函数名(参数)"
3、事件对象如何获取
	如阻止事件的默认行为:e.preventDefault()
	1)调用时不传参数时,默认就在第一个形参
	2)如果传递参数了,需要在实参处写上$event,然后形参处接收
     例如:@事件类型="函数名($event,66)"
4、简化版:
	@事件类型.prevent = "事件处理函数"//阻止事件默认行为
	@事件类型.stop = "事件处理函数"//阻止冒泡
	@事件类型.stop.prevent = "事件处理函数"//阻止冒泡和默认行为
	特殊的事件如keyup事件
		@keyup.enter = "事件处理函数"//抬起并按下了回车,才会触发
		@keyup.ctrl.enter = "事件处理函数"
		......

5、条件渲染

1、v-if:
	原理:使用js中创建和删除标签//切换一次耗一次性能
2、v-show:
	原理:使用js中的display的block和none来控制//初始时消耗一次
3、安全性:v-if高于v-show
4、支持写在template标签上//辅助标签,不会显示出来
	1.v-if支持
	2.v-show不支持

6、循环

1、语法:v-for="item in 数字"//想让谁出现多次,就把v-for写在谁神身上
	例如:<span v-for="(item,index) in 10" :key="index"></span>
	//key后要写唯一的东西,例如索引等
2、遍历数组:v-for = "(item,index) in data中的数组" :key="唯一的"
	//item则是数组中每一个值
3、遍历对象:v-for = "(value,key) in data中的对象" :key="唯一的"
	//value则是对象中每一个值
//v-for的默认行为会尝试原地修改元素而不是重新创建

7、v-if和v-for的优先级

     vue3中,v-for和v-if的优先级谁更高//v-if优先级高
     vue2中,v-for和v-if的优先级谁更高//v-for优先级高
//如果v-for优先级高,这就意味着v-if将重复的运行于每一个v-for循环中
//注意:v-if和v-for尽量不要写在一个标签上,将判断写在template标签上,循环写在里面的标签

8、综合小demo(简易购物车)

<body>
    <div id="app">
        <table border="1">
            <thead>
                <tr>
                    <td>商品名称</td>
                    <td>商品单价</td>
                    <td>商品数量</td>
                    <td>商品小计</td>
                    <td>商品操作</td>
                </tr>
            </thead>
            <tbody>
                <tr v-for="(item,index) in list" :key="item.index">
                    <td>{{item.product}}</td>
                    <td>{{item.price}}</td>
                    <td>
                        <button @click="jianNum(item.id)">-</button>
                        <span>{{item.num}}</span>
                        <button @click="jiaNum(item.id)">+</button>
                    </td>
                    <td>{{item.num*item.price}}</td>
                    <td><button @click="remove(item.id)">删除</button></td>
                </tr>
            </tbody>
            <tfoot>
                <tr>
                    <td colspan="5">
                        <span>总数:{{list.reduce((sum,item)=>sum+=item.num,0)}}</span>
                        <span>总价:{{list.reduce((sum,item)=>sum+=item.num*item.price,0)}}</span>
                    </td>
                </tr>
            </tfoot>
        </table>
    </div>
</body>

</html>
<script src="lib/vue.global.js"></script>
<script>

    Vue.createApp({
        data() {
            return {
                list: [
                    { id: 1, product: "小米手机", price: 10, num: 1 },
                    { id: 2, product: "华为手机", price: 60, num: 1 },
                    { id: 3, product: "红米手机", price: 30, num: 1 },
                    { id: 4, product: "锤子手机", price: 30, num: 1 },
                    { id: 5, product: "小灵通手机", price: 10, num: 1 }
                ]
            }
        },
        methods: {
            jiaNum(id) {
                this.list.find(item => item.id == id).num++;
            },
            jianNum(id) {
                let good = this.list.find(item => item.id == id);
                good.num = good.num <= 1 ? 1 : --good.num;
            },
            remove(id) {
                this.list = this.list.filter(item => item.id != id);
            }
        }
    }).mount('#app')
</script>

9、计算属性

1、概念:模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。依赖其他属性计算而来的属性,可以写到computed选项中,写起来像方法,使用起来是属性。
2、计算属性 vs 方法
	1)使用的时候,方法需要带() 计算属性不需要带()
	2)计算属性值会基于其响应式依赖被缓存。当依赖项不发生,直接从缓存中取,当依赖项发生变化,会重新调用一次
3、语法://计算属性的名字不可以和data中变量名相同
	语法一://这种写法值不可修改,只读
	 computed: {
            计算属性的名字:function(){
                return ;
            } 
        }
	语法二://这种写法值可读可写
	 computed: {
            计算属性的名字: {
                // 获取的语法
                get() {
                    return;
                },
                set(val){
                }
            }
        }

10、侦听器

1、概念:侦听data中数据的变化
2、语法:
	语法一://侦听的直接是基本类型属性
      watch:{
          "哪个data":function(newval,oldval){}
      }
     语法二://侦听对象
	watch:{
 		"侦听哪个对象":{
               deep:true//深度侦听
               immediate:true,//立即侦听,页面打开立即侦听
               handler(newval,oldval){//newval变化后,oldval变化前
                    newval: 改变后的对象的值,对象中所有的属性都在newval包含
               }
		}
	}
	语法三://手动开启侦听
	this.uwatch = this.$watch('侦听的属性',(newval=>{}))//开启侦听
	this.uwatch();//结束侦听
3、watch 默认是懒执行的:仅当数据源变化时,才会执行回调。
	可以用一个对象来声明侦听器,这个对象有 handler 方法和 immediate: true 选项,这样便能强制回调函数立即执行

11、样式的绑定

1、基本绑定样式:
	例:<p :class="active"> 白日依山尽 </p>
2、对象的方式:
	例:<p :class="{'常量型类名':true,'常量型类型':true}"></p>
	//键作为类名,值为布尔,为true则键作为类名加在p上
3、数组的方式: 
	例:<p :class="['常量型类名',变量型类名]"></p>
	//将[常量型类名]和[变量型类名]作为类名加在p上
4、style的方式:
	例:<p :style="{属性名:'属性值(常量要带引号/变量)',fontSize:'28px'}"></p>
	//常量带-的要用驼峰

12、vue2的响应式

const vm = new Vue({
     el:'#app',
     data:{}
})
1、data和vm关系:
	vm是data的代理对象
	Object.defineProperty 通过代理对象vm,能够捕获到对象源data的修改和获取操作,无法捕获到添加和删除

3、选项式

1、Object.defineProperty和proxy

1、Object.defineProperty:
	限制一:只能捕获到对象的获取和设置,不能捕获对源对象的添加和删除
	限制二:js的限制,无法捕获到数组中某个值的变化,数组的方法操作也无法捕获
	//vue中重写了push、pop、shift、unshift、splice、reverse、sort能改变原数组的方法,让这些方法可以触发set方法,从而触发watch侦听,从而更新页面
	不改变原数组的方法,可以通过赋值,覆盖原数组的方式,触发自动更新
	
	通过数组下标修改数据不会触发自动更新,需要强制更新
	vue里还提供了,强制更新数据到页面的方法:
		this.$forceUpdate()

2、过滤器

概念:处理一些数据的//例如时间戳的处理
{{过滤前 | 过滤后}}//标签里

     data:{
          过滤前:value
     }
	语法一:
     filters:{//过滤器
          过滤后:function(val){     
               console.log(val)//处理
          }
     }
	语法二:
	  filters:{//过滤器
          过滤后:function(val,形参){     
               console.log(val+形参)//处理
          }
     }

3、内置指令

概念:上面学习的都是内置指令
1、v-cloak指令:
	是一个特殊属性,写在标签上,配合css里设置[v-cloak]{display:"none"}
	可以防止页面出现,未解析完毕的内容,如{{xxx}}...
2、v-once指令:
	v-once所在标签在初次渲染完毕后,就会视为静态内容,以后数据改变,不会引起v-once所在结构的更新,用于优化性能。
3、v-pre指令:
	让vue跳过其所在标签,不对其进行解析,优化,加快编译

4、组件化

1、创建语法:
	//app.component("组件名字",{组件中的内容})
	//定义了一个全局的组件
     app.component("myHeader", {
         template: `
`
, data() { return { msg: 'header子组件' } }, methods: {} }) //定义了一个局部的组件 app.component("myHeader", { template: `
`
, data() { return { msg: 'header子组件' } }, components:{//这里写的就是局部组件 } methods: {} }) //vue2定义组件 const 组件名 = Vue.extend({}) 简写语法:const 组件名 = {组件内容} 2、使用语法://驼峰转换为小写,-连接 <my-header></my-header>
4.1、VueComponent构造函数(vue2里)
1、组件本质是一个名为VueComponent的构造函数,是由Vue.extend生成的
2、是需要写'',Vue解析时会帮我们创建school组件的实例对象,即调用new VueComponent(options)
3、每次调用Vue.extend时返回的都是一个全新的VueComponent
4this指向:
	1)组件配置中:
		data、methods、watch、computed中的函数,this指向为VueComponent实例对象
	2new Vue(options)配置中:
		data、methods、watch、computed中的函数,this指向为Vue实例对象
5、VueComponent组件实例对象

5、组件通信1
一、props配置项:
     1、功能:让组件接收外部传过来的数据//组件通信之父传子
     2、传递数据:在父组件里给子组件加动态属性(通过v-bind绑定属性方式),属性值为父组件的数据
          <Demo :name='xxx'/>
     3、接收数据:
          方式一:(只接收):props:['name']
          方式二:(限制类型):props:{name:String}
          方式三:(限制类型、限制必要性、指定默认值)props:{
               name:{
                    type:String,//类型
                    required:true, //必要性
                    default:'张三'//默认值
               }
          }
     4、props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,必须要修改时,可以复制一份新的,修改新的数据
     
二、组件通信之字传父:
	1.在父组件里给子组件的标签上设置一个自定义事件,事件处理函数就是写在父组件的方法
	2.在子组件中使用emits接受父组件传递过来的事件名
	3.在子组件内合适的时机(点击按钮等),触发自定义事件执行,并传参给父组件

6、脚手架

1、搭建:vue3
	1)安装node(16以上的版本)
	2)npm init vue@latest//下载vue说明书
		Project name //文件名
		默认no直接回车...
	3)cd 文件名 //进入到创建的文件
	4)npm i //下载说明书里的第三方模块
	5)npm run dev /vue项目
	6)删除vue里的无用文件
2、各个文件作用:
	public 
		favicon.ico:页签图标
	src
		assets://静态资源
		components://用于存放组件的文件夹
		App.vue:汇总所有组件
		main.js://整个项目的入口文件
			import { createApp } from 'vue' //解析出vue实例
			import App from './App.vue' //导入app组件,它是所有组件的父组件
			createApp(App).mount('#app') //创建vue实例对象---vm
	index.html:主页面
	.gitignore://git忽略文件
	babel.config.js://babel控制文件,用于将es6转为es5
	package-lock.json://包版本控制文件
	package.json: //说明书
	README.md://文档
3、使用
	1)在app.vue书写核心组件 
	2)components里书写其他组件 
	组件里必须包含
          <script></script>
          <template></template>
          <style scoped></style>
          //scoped让样式在局部生效,防止冲突
	3)子组件功能书写完毕后,将组件导入到核心组件里,拼为一个完整页面
	4)终端输入 output.js //将vue脚手架默认配置整理成一个js文件

7、透传attribute:

	1、概念:父组件传递给子组件时,子组件没有接受父组件传递的属性,子组件最终会渲染成标签,同时传递的数据都绑定在这个标签上,数据可以通过$attrs.属性名来获取属性值
	2、子组件使用props接收父组件传递的属性,则会渲染为标签,同时传递的数据没有绑定在这个标签上
父组件传递数据给子组件时,子组件没有使用emits接收父组件传递的事件,子组件中可以直接触发这个事件
不想接收透传的属性,可以将inheritAttrs

8、 r e f s 、 refs、 refsparent、$root

1、ref:获取标签,使用时用$refs
	1)被用来给元素或子组件注册引用信息//代替id
	2)应用在html标签上获取的是真实的dom元素,应用在组件标签上是组件实例对象
	3)使用方式:
		打标识:<h1 ref='xxx'>...</h1>
		获取:this.$refs.xxx
2、$parent:触发父组件
	在子组件中拿父组件的属性和方法
3、$root:触发根组件
	在孙组件中拿根组件中的属性和方法

9、生命周期

vue.js学习笔记_第3张图片

1、含义:又名(生命周期回调函数、生命周期函数、生命周期钩子,Vue,关键时刻帮我们调用的一些特殊名称的函数,具体时间做具体的事情,分为四个阶段,八个生命周期//this指向都为vm或组件实例对象
2、四个阶段:
	1)创建阶段:
		beforeCreate//创建实例前
		created//创建完成
	2)挂载阶段
		beforeMount//挂载前(挂载到dom上)
		mounted//挂载完成***
	3)更新阶段(触发更新,数据变化,dom元素新增和删除)
		beforeUpdate//更新前
		updated//更新
	4)销毁阶段
		Vue2: beforeDestory//销毁前***   destoryed//销毁后
		Vue3: beforeUnMount//销毁前***   unmounted//销毁后
3、常用的声明周期钩子:
	1)mounted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】
	2)beforeUnMount:清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】
4、销毁Vue实例 //手动删除vm this.$destroy()
	1)销毁后借助Vue开发者工具看不到任何信息
	2)销毁后自定义事件会失效,但原生Dom事件依然有效
	3)一般不会再beforeDestroy操作数据,因为即使操作数据了,也不会触发跟新流程了

10、组件通信2

1、兄弟组件传值:
	vue2:先实例化一个公共的通信对象eventBus,其中一个组件通过$on监听事件,另外一个兄弟组件通过$emit去触发事件
2、跨组件传值:外层组件通过provide选项传值,内层组件通过inject传值

11、插槽

1、作用:自定义组件内容
2、	默认插槽:不需要起名<slot/>
	具名插槽:需要起名<slot name=""/>

12、内置组件

12.1、动态组件和缓存组件
1、component动态组件
2、keep-alive:缓存组件,包裹在需要缓存的组件外部,被缓存的组件会保留在内存中,组件下次切换时只需要从内存中读取并显示出来即可
	//include---指定需要缓存的组件列表(使用时必须给组件设置name)
	//exclude---指定不需要缓存的组件列表
     <keep-alive include="ChildA,ChildB" exclude="ChildC">
          <component :is="组件"/>
     </keep-alive>
3、与keep-alive搭配使用的两个钩子函数:
	deactivated//进入缓存
	activated//激活组件
12.2、动画组件
transition:动画组件//Transition包裹的必须是一个单根的组件
<transition name="默认v" mode="出入顺序"><transition>
对象的选择器:vue3
	.name名-enter-from: 入场动画开始前的状态
	.name名-enter-active: 入场动画开始后的状态
	.name名-leave-from: 离场动画开始前的状态
	.name名-leave-active: 离场动画开始后的状态
mode:出入顺序
	out-in:先出后入
	in-out:先入后出

13、自定义指令

1、自定义指令:directives//用于封装自定义指令
	//定义时不加v-,使用时要写加v-
2、局部指令:
	directives:{
           自定义指令名:{
               //在绑定元素的父组件及他自己的所有子节点都挂载完成后调用
               mounted(el, binding, vnode, prevVnode) {
				el:指令绑定到的元素。这可以用于直接操作 DOM}
           }
	}
	//自定义指令中的this都是window
	
2、全局自定义指令//任何组件都可已使用
	//简化形式
	app.directive('指令名',(element,binding){
		// 这会在 `mounted` 和 `updated` 时都调用
		//element真实dom元素,binding本次绑定的信息
	})

14、插件

功能:用于增强Vue
本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。
定义插件:
	myplugins
	export default{
		install(app){}
     }
导入插件:import myplugins from '路径/myplugins'
使用插件:app.use(myplugins插件名)

15、混入

1、功能:抽离多个组件的公共代码(选项),将抽离的代码放在单独的文件里,需要用时引入,避免代码冗余。 //单独文件(mixins)里能写在都是已有的选项
2、使用:mixins:[],混入的公共代码会出现在选项内

16、api

$forceUpdate()//让组件强制更新
$nextTick()//可以让特定代码在组件的下次更新周期到后再执行

17、路由

1、概念:单个页面,通过地址栏地址变化,跳转不同页面实现更新页面内容的技术
2、在vite构建的vue单页面应用中,需要借助vue-router库,实现路由功能
3、配置路由表:
	单条路由的配置:
		{path:'/login',component:Login}
	嵌套路由:
		{
             path:'/index',//地址后写什么
             component:Index//组件
             children:[]//嵌套的路由必须跟在/index/后面
         },
	重定向:{path:'/',redirect:'/index'}
	404{path:'/:error(.*)',component:NotFound}
4、路由组件
	<router-link to="用来跳转路由">//最终渲染成a标签
	router-view//充当路由渲染出口
5、路由实例:
	$router//路由管理对象,负责跳路由
	$route//路由对象,负责存储路由信息
6、条路由的两种方式:
	标签式导航:借助router-link渲染的a标签来跳转
	编程式导航:借助$router的push,go方法来跳路由
7、条路由传参:
	动态路由传参:
		配置路由:{path:'/detail/:id',component:Detail}
		传参:this.$router.push("/detail/"+参数)
		接参:this.$route.params.id
	固定路由传参:
		传参:this.$router.push({path:"/detail/",query:{id}});
		接参:this.$route.query.id
8、parmas和query的区别
	parmas在地址栏不显示key,而query的key和value都显示,前者更安全;
	parmas上线率先你会丢失,query不会;
	语法不同
9、组件内---对某些组件进行路由跳转时生效
     进入组件时//beforeRouteEnter		
     离开组件时//beforeRouteLeave

17.1、路由懒加载(延时加载)
1、概念:为了减少页面加载时间,在需要的时候再调用对应的js文件。
	用懒加载方式导入每个组件,每个组件都会单独生成一个js文件,当你实际访问哪个路由,对应的组件文件才会加载,否则不加载。
2、使用:var MyIndex = () => import('../views/MyIndex.vue');

17.2、路由守卫
1、概念:在到跳路由前、后做的一些操作//比如跳购物车页面判断下是否登录
2.语法:
	router.beforeEach((to,from,next)=>{//全局前置守卫函数
		to//去往哪里的路由对象,判断是否携带token,没带跳登录
          from//来自哪里的路由对象
          next('/login')//不写参数放行,写了就是强制跳该路由
     })
	//全局后置守卫函数
	router.afterEach()
3、应用:
	1)控制路由跳转
	2)配合nprogress实现进度条的播放
          import nProgress from 'nprogress'
          import 'nprogress/nprogress.css'
          nProgress.start();//开始播放进度条动画
          nProgress.done();//停止播放进度条动画

18、组件库

1、移动端:vant UI
2PC端:
	element UI//vue2
	element plus//vue3

19、使用axios发送网络请求

1、概念:基于Promise的Http请求工具库,支持浏览器端和NodeJS端
2、下载axios插件、并对其进行封装
3、实例化一个axios对象,并在其上添加拦截器
	var service = axios.create{//1.实例化axios
		timeout: 毫秒, //超时时间
		baseURL: '', //基准路径,比如写个/api,则以/api开头的可以省略/api
	}
	service.interceptors.request.use(//2.设置 请求 拦截器
		//请求从本地发给服务器之前执行,一般用于添加请求头
		(config)=>{return config;}, 
		(error) => {return Promise.reject(error);} //请求发生错误时的处理
	) 
	service.interceptors.response.use{//3.设置 响应 拦截器
		(res)=>{return res;}, //请求从服务器发送回来时执行
		//对请求发生错误时的处理,一般用于判断不同状态码做对应处理
		(error) => {return Promise.reject(error);}
	} 
	export default service;//导出
4、配置代理
	1)概念:如果不做配置,默认发送的ajax请求,会发给vscode临时开启的服务器
     server: {
          proxy: {//代理
               '/api': {//所有以/api开头的请求都会发送给目标服务器
                    target: '目标服务器地址', //目标服务器
                    changeOrigin: true,//开始跨域
               }
          }
     }
5、发送请求,并将每一个接口封装成一个函数,并导出//便于统一管理
封装:
	export function (参数 = {}) {
		//get
		return service.get('地址', { params:  参数  })
		//post
		return service.post('地址', 参数 );
	}
使用: 
	import * as service from '路径';//集体导入到一个对象中
	import { login } from '路径';//命名导入( 按需导入 )
	service.({ 参数}).then((res)=>{
		console.log(res.data);//数据
	})

19.1、发请求出现错误需要注意的小细节
1、打开浏览器在network里检查//文件名默认是请求地址最后一个单词
	Headers:检查请求地址是否正确,请求头是否携带
	Preview:检查返回的数据
2get请求参数格式:{params:{}}
     post请求参数格式:{}

20、vuex插件(状态管理模式+库)

概念:Vuex是一个专为Vue.js应用程序开发的状态管理模式+库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

1、下载vuex插件,通过createStore实例创建一个store存储库
https://vuex.vuejs.org/zh/guide/#%E6%9C%80%E7%AE%80%E5%8D%95%E7%9A%84-store
createStore({
	state:{},//负责存储数据
	getters:{},//定义计算方法(类似于计算属性,必须有返回值)
	mutations:{},//定义同步方法(可以直接修改state中的数据)
	actions:{},//定义异步方法(内部可以实行异步代码,但不能直接修改state中的数据)
	modules:{},//模块化管理state中的数据
	plugins:[]//配合其他插件管理state中的数据
})
2、使用:
	this.$store.commit('同步方法名',参数)
	this.$store.dispatch('异步方法名',参数)
	this.$store.getters.计算方法名
3、其他插件
	vuex-persistedstate//用于对state持久化存储
	createLogger//日志打印插件,用于打印state数据
	npm install vuex@next --save//安装vuex
	npm install vuex-persistedstate//安装vuex-persistedstate
	直接调用即可
		plugins:[createPersistedState(),createLogger()]
20.1、vuex状态管理模式的补充
1、模块化管理:vuex里state存放数据,而每一个数据对应着许多方法,如果存放的数据过多,那么就会导致有许多的方法写在一起,不方便管理,所有将一个数据拆分成一个模块,单独一个文件,用于管理该数据,再将所有模块统一管理。
2、模块的定义及管理
	创建一个modules文件夹,用于存放模块
	1//模块的定义
     export default {
        namespaced:true, //让当前模块变成拥有自己独立作用域的私有模块
		state:{},getters:{},mutations:{},actions:{}
     }
	2//管理模块
	import tasklist from './modules/tasklist'
	import shopcart from './modules/shopcart'
	//所有被管理模块都可以使用这里的数据,方法,插件
	export default createStore({
		state:{},getters:{},mutations:{},actions:{}
		modules:{ //以模块化的方式管理state数据( 这里决定了每个模块的名字 )
             tl:tasklist, //t1模块别名,tasklist模块名
             sc:shopcart,
		},
		plugins:[ createLogger() ]
     })
	3)使用:
          this.$store.state.模块名.xx
          this.$store.getters['模块名/xx']
          this.$store.commit['模块名/同步方法']
          this.$store.dispatch['模块名/异步方法']
		例:this.$store.dispatch( 'tl/request' );//调用了t1模块里面的异步方法:request
3、辅助函数
	//mapActions() 将vuex中的异步方法映射到当前组件的methods中
	//mapMutations() 将vuex中的同步方法映射到当前组件的methods中
	//mapState() 将vuex中的数据映射到当前组件的computed中
	//mapGetters() 将vuex中的计算方法映射到当前组件的computed中

1)用法:
import { mapActions, mapMutations, mapState,mapGetters } from 'vuex'
	//直接写在计算属性(computed)里
	...mapState('模块名', ['模块里的属性名'])
	...mapGetters('模块名',['模块里的计算属性名','模块里的计算属性名'])
	//直接写在方法(methods)里
	...mapActions('模块名', ['模块里的异步方法名']),
	...mapMutations('模块名', ['模块里的异步方法名', '模块里的异步方法名']),
	映射后就可以直接通过this.方法(属性)名的方式直接调用

组件化编码流程:

###1、组件化编码流程(通用)
	1)实现静态组件:抽取组件,使用组件实现静态页面效果
	2)展示动态数据:
		2.1.数据的类型、名称是什么?
		2.2.数据保存在哪个组件?
	3)交互-从绑定事件监听开始

下载需要用到的库
创建并配置一级路由及相关组件,并验证,以此类推创建二级等
二次封装axios:实例化axios,并设置拦截器//添加请求头和对错误的处理等
使用axios的二次封装,进行对不同接口的封装,统一管理
可以使用awaitasync使请求按顺序发送
省略号:
	overflow:hidden;
	display:-webkit-box;
	-webit-box-orient:vertical;
	-webit-line-clamp:2;

4、组合式

1、组合式的语法
1、setup声明周期函数(代替的是beforeCreate和created)
	1)setup特点:
          组件实例化时执行
		thisundefined
		定义的所有数据和方法都要return返回
2、vue3组合式组件通信
	1)父向子传值:
		父组件通过自定义属性传值,子组件props接收值,
		也可以通过setup(props){}//setup第一个参数为props
	2)子向父传值:
		父绑定自定义事件,子通过emit触发事件并传值
		setup(props,{emit})//setup第二个参数可以解构出emit
	3)兄弟组件传值:
		下载mitt插件,通过mitt实例化通信对象 export default mitt;
		使用:导入通信对象,通过mitt.on提前绑定监听事件,mitt.emit触发事件
3、vue3组合式路由:
	1import {useRouter} from 'vue-router'
	  获取路由管理对象 var router = useRouter();
	  获取路由对象 var route = useRoute();
4、vue3组合式生命周期的变化:
	将beforeCreate和created合并为了setup
	其他声明周期前面都加了on,如onBeforeMount,且都要写在setup里
vue3组合式里没有this:
	发请求等操作需要使用其他属性时,直接使用即可,不需要this
vue3组合式使用其他组件时,只需要导入,不需要注册,直接使用即可
5、定义响应式数据:
	//两个api函数
	1)reactive()//用于将引用类型数据转化为响应式数据(基本数据类型不能转化)
		var count = reactive([0])
		在js代码中获取reactive类型数据的原始值,直接使用即可
		reactive解构后会丢失响应式,需要通过toRefs转化为响应式,在解构
	2)ref()//可以将基本和引用类型数据转化为响应式数据
          var count = ref(0)
          (js)代码中获取ref类型数据的原始值,必须借助.value属性
          在模板中使用不需要带.value
	3)toRefs//将reactive定义的响应式数据中的每个属性转化为Ref定义的响应式数据
6、定义方法、计算属性、watch
	1)定义方法:var fn = ()=>{}
	2)定义计算属性: var sum = computed(()=>{});
	3)watch:
		watch(count,(newVal,oldVal)=>{});//监听单个
		watch([count,obj],(newVal,oldVal)=>{})//监听多个
		watch(obj,(newVal,oldVal)=>{},{deep:true})//开启深度监听写法

2、状态管理pinia(与vuex)

1、pinia(与vuex)相同点:
	1)都是状态管理库,都可以用于vue2、vue3
	2)都支持响应式数据,可以在组件中轻松地访问和修改状态。
	3)默认都没有持久化,需要手动开启
2、不同:
	vuex使用的选项式的语法
	pinia使用的组合式的语法
3、使用步骤:
     npm install pinia
     npm i pinia-plugin-persistedstate --save//持久化插件 
	在main.js中引入持久化插件
		import {createPinia } from "pinia";
		import piniaPluginPersistedstate from "pinia-plugin-persistedstate";//pinia持久化
		const pinia = createPinia();
		pinia.use( piniaPluginPersistedstate );
		app.use(pinia)
	//持久化开启
	export const loginStore = defineStore('main',()=>{},persist:true)

3、补充

自动导包插件:npm i unplugin-auto-import -D 
   并在vite.config.js配置
	import AutoImport from 'unplugin-auto-import/vite'
	plugins: [
		vue(),
		AutoImport({
			imports:['vue','vue-router']//自动导入vue和vue-router相关api
		})
	],
@:代表了src
	原引用文件的方式:import * as service from './api'
	新引用文件的方式:import * as service from '@/api'//所有文件通用

4、组件式写法二

1、setup语法糖写法:
	<script setup>不用return</script>

5、pc端项目

1、router、pinia、element UI 及两个自动化插件并做配置
2、路由及路由表拆分、axios的封装(拦截器)、请求的统一归类并模块化
3、表单组件:
	rules:设置验证规则
	通过ref绑定from实例,submit(ref)接收,validate做校验
4、pinia数据存储的

6、element ul 使用

1、配置:
	npm install element-plus --save//下载
	npm install -D unplugin-vue-components unplugin-auto-import//自动导入
     //并在vite.config.ts做配置
     plugins: [
         // ...
         AutoImport({
           resolvers: [ElementPlusResolver()],
         }),
         Components({
           resolvers: [ElementPlusResolver()],
         }),
       ],
2、icon图标
	1)安装包:npm install @element-plus/icons-vue
	2)main.ts里注册
          import * as ElementPlusIconsVue from '@element-plus/icons-vue'

          const app = createApp(App)
          for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
            app.component(key, component)
          }

7、部分内容总结

day01

1、组件通信:

1)父组件向子组件传值:父组件在子组件上,通过自定义属性传值,子组件内部通过props接收自定义属性,获取值
2)子组件向父组件传值:父组件需要在子组件身上绑定自定义事件,子组件内部通过$emit触发事件并传值
3)兄弟组件传值:
	//只支持vue2
	先实例化一个公共的通信对象eventBus,其中一个组件在挂载完毕mounted()生命周期函数里,通过$on提前绑定监听事件,另外一个兄弟组件在特定情况通过$emit去触发事件,并传值
4)跨组件传值:外层组件通过provide选项传值,内层组件通过inject选项接收值
5)v-model的特殊使用方式:
	//vue3默认写法,update:modelValue必须这样写
	方式一:父组件在子组件上,通过v-model="value"双向绑定,在子组件的input上使用		
          	@input="$emit('update:modelValue', $event.target.value)
     //父组件加:自定义的方式,update:自定义
	方式二:父组件在子组件上,通过v-model:abc="value"双向绑定,在子组件的input上使用		
          	@input="$emit('update:abc', $event.target.value)
	//vue2默认写法:input
	方式一:@input="$emit('input', $event.target.value)
	//自定义方式
	方式二:model{prop:'abc',event:'bbb'}
		@input="$emit('bbb',$event.target.value)"

2、ref

写在标签上,获取的是所在标签的dom节点
写在自定义组件上,获取的是所在组件的实例//可以调用其上的方法

3、component和keep-alive

1、component动态组件
2、keep-alive:缓存组件,包裹在需要缓存的组件外部,被缓存的组件会保留在内存中,组件下次切换时只需要从内存中读取并显示出来即可
	//include---指定需要缓存的组件列表(使用时必须给组件设置name)
	//exclude---指定不需要缓存的组件列表
     <keep-alive include="ChildA,ChildB" exclude="ChildC">
          <component :is="组件"/>
     </keep-alive>
3、与keep-alive搭配使用的两个钩子函数:
	deactivated//进入缓存
	activated//激活组件

4、插槽

1、作用:自定义组件内容
2、	默认插槽:<slot/>//占位
	具名插槽:<slot name=""/>

day02

1、动画组件

用于定义动画:<transition name="默认v" mode="出入顺序"><transition>//内部只能包裹一个标签
name:默认v,用于充当类名如:.name名-enter-from{书写动画}
mode:out-in:先入后出,in-out反之

2、自定义指令

局部指令:通过directives选项来定义,指令名:{使用钩子函数编写操作},只能在当前组件使用
全局指令:通过app.directive方法定义,指令名:{使用钩子函数编写操作},可以在任何组件使用

3、自定义插件

定义://创建一个js文件
     export default(){
          install(app){}
     }
使用:在main.js里引入定义的插件,app.use(插件名)//use方法执行时自定执行了install方法

4、mixins混入

1、功能:抽离多个组件的公共代码(选项),将抽离的代码放在单独的文件里,需要用时引入,避免代码冗余。 //单独文件(mixins)里能写在都是已有的选项
2、使用:mixins:[],混入的公共代码会出现在选项内

5、forceUpdate和nextTick两个核心api

$forceUpdate()//让组件强制更新
$nextTick()//可以让特定代码在组件的下次更新周期到后再执行

day03

1、路由

1、概念:单个页面,通过地址栏地址变化,跳转不同页面实现更新页面内容的技术
2、在vite构建的vue单页面应用中,需要借助vue-router库,实现路由功能
3、配置路由表:
	单条路由的配置:
		{path:'/login',component:Login}
	嵌套路由:
		{
             path:'/index',//地址后写什么
             component:Index//组件
             children:[]//嵌套的路由必须跟在/index/后面
         },
	重定向:{path:'/',redirect:'/index'}
	404{path:'/:error(.*)',component:NotFound}
4、路由组件
	<router-link to="用来跳转路由">//最终渲染成a标签
	router-view//充当路由渲染出口
5、路由实例:
	$router//路由管理对象,负责跳路由
	$route//路由对象,负责存储路由信息
6、条路由的两种方式:
	标签式导航:借助router-link渲染的a标签来跳转
	编程式导航:借助$router的push,go方法来跳路由
7、条路由传参:
	动态路由传参:
		配置路由:{path:'/detail/:id',component:Detail}
		传参:this.$router.push("/detail/"+参数)
		接参:this.$route.params.id
	固定路由传参:
		传参:this.$router.push({path:"/detail/",query:{id}});
		接参:this.$route.query.id

day04

1、路由懒加载

1、概念:为了减少页面加载时间,在需要的时候再调用对应的js文件。
	用懒加载方式导入每个组件,每个组件都会单独生成一个js文件,当你实际访问哪个路由,对应的组件文件才会加载,否则不加载。
2、使用:var MyIndex = () => import('../views/MyIndex.vue');

2、路由守卫

1、概念:在到跳路由前、后做的一些操作//不如跳购物车页面判断下是否登录
2.语法:
	router.beforeEach((to,from,next)=>{//全局前置守卫函数
		to//去往哪里的路由对象
          from//来自哪里的路由对象
          next('/login')//不写参数放行,写了就是强制跳该路由
     })
	//全局后置守卫函数
	router.afterEach()
3、应用:
	1)控制路由跳转
	2)配合nprogress实现进度条的播放

3、使用axios发送网络请求

1、概念:基于Promise的Http请求工具库,支持浏览器端和NodeJS端
2、下载axios插件、并对其进行封装
3、实例化一个axios对象,并在其上添加拦截器
	var service = axios.create//1.实例化axios
	service.interceptors.request.use(//2.设置 请求 拦截器
		(config)=>{}, //请求从本地发给服务器之前执行
		(error) => {} //请求发生错误时的处理
	) 
	service.interceptors.response.use{//3.设置 响应 拦截器
		(res)=>{}, //请求从服务器发送回来时执行
		(error) => {}//对请求发生错误时的处理
	} 
	export default service;//导出
4、配置代理
	1)概念:如果不做配置,默认发送的ajax请求,会发给vscode临时开启的服务器
     server: {
          proxy: {//代理
               '/api': {//所有以/api开头的请求都会发送给目标服务器
                    target: '目标服务器地址', //目标服务器
                    changeOrigin: true,//开始跨域
               }
          }
     }
5、发送请求,并将每一个接口封装成一个函数,并导出//便于统一管理
封装:
	export function (参数 = {}) {
		//get
		return service.get('地址', { params:  参数  })
		//post
		return service.post('地址', 参数 );
	}
使用: 
	import * as service from '路径';//集体导入到一个对象中
	import { login } from '路径';//命名导入( 按需导入 )
	service.({ 参数}).then((res)=>{
		console.log(res.data);//数据
	})

day05

1、vuex插件(状态管理模式+库)

1、下载vuex插件,通过createStore实例创建一个store存储库
https://vuex.vuejs.org/zh/guide/#%E6%9C%80%E7%AE%80%E5%8D%95%E7%9A%84-store
createStore({
	state:{},//负责存储数据
	getters:{},//定义计算方法(类似于计算属性,必须有返回值)
	mutations:{},//定义同步方法(可以直接修改state中的数据)
	actions:{},//定义异步方法(内部可以实行异步代码,但不能直接修改state中的数据)
	modules:{},//模块化管理state中的数据
	plugins:[]//配合其他插件管理state中的数据
})
2、使用(api):
	this.$store.commit('同步方法名',参数)
	this.$store.dispatch('异步方法名',参数)
	this.$store.getters.计算方法名
3、相关插件
	vuex-persistedstate//用于对state持久化存储
	createLogger//日志打印插件,用于打印state数据
	npm install vuex@next --save//安装vuex
	npm install vuex-persistedstate//安装vuex-persistedstate
	直接调用即可
		plugins:[createPersistedState(),createLogger()]


week01

1、组件

1、组件通信:
	父组件向子组件传值:父组件在子组件上写一个自定义属性传值,子组件通过props接收值
	子组件向父组件传值:父组件在子组件上绑定自定义事件,子组件通过$emit触发事件并传值
	兄弟组件传值:借用一个公共的通信对象,接收值的组件通过$on提前定义好监听事件,发送值的组件通过$emit触发事件,并传值
	跨级传值:外层组件通过provide传值,内层组件通过inject接收值,外层发一次,所有内层都可接收
2、内置组件:
	component//动态组件,通过is属性切换页面
	keep-alive//缓存组件,include缓存,exclude不缓存
	transition//动画组件,.name名-enter-from{书写动画},mode out-in先出后进
	slot//插槽
3、自定义指令:
	局部指令:组件内用directives:{}
	全局指令:全局可用app.directive()
4、mixins//混入,抽离公共代码,避免代码冗余


2、路由

1、配置:
	单条路由:{path:'路由地址',component:组件名}
	嵌套路由:{children:[]}
	重定向:{redirect:'重定向地址'}
	404{path:'/:error(.*)',component:组件名}
2、路由组件:
	router-link//渲染a标签,实现路由跳转
	router-view//路由渲染出口
3、路由实例
	$router//路由管理对象,负责跳路由
		push()、go()、replace()
	$route//路由对象,负责存储路由相关信息(地址,参数)
4、跳路由传参:
	动态路由传参:params
		定义:{path:'/detail/:id'}
		跳路由传参:$router.push('/detail/'+参数)//参数是对象需要转字符串
		接参:$route.params.id
	固定路由传参:query
		传参:$router.push({path:'/detail',query:{参数}})
		接参:$route.query.id
5、路由懒加载://每个组件都会单独生成一个js文件,当你实际访问哪个路由,对应的组件文件才会加载
	var Detail = ()=>import('文件路径')
6、守卫函数://应用:控制路由访问权限,进度条动画播放...
	全局前置守卫函数:beforeEach((to, from, next)=>{}
	全局后置守卫函数:router.afterEach((to, from) => {}


3、组件库

	vant UI使用步骤:
		下载vant npm i vant
		下载并配置插件:npm i unplugin-vue-components -D//并配置vite.config.js
		使用组件:直接在vue文件里使用


4、网络请求(axios)

1、发送请求方式:
	axios({method:'get'})
	axios.get()
	axios.post()
2、二次封装
	实例化axios
	设置请求拦截器//可以添加请求头参数,比如token
	设置响应拦截器//判断错误的响应码
3、统一管理请求:一个请求封装为一个函数,并导出每个函数


5、状态管理(vuex)

1、vuex:是一个专为vue.js应用程序开发的状态管理模式+库,它采用集中式存储管理应用的所有组件的状态,并以响应的规则保证状态以一种可预测的方式发生变化。
2、store:
	下载:npm i vuex
	实例化: export default createStore({})
	应用:import store from './store'
		app.use(store)
3、核心
	state:{},//负责存储数据
	getters:{},//定义计算方法(类似于计算属性,必须有返回值)
	mutations:{},//定义同步方法(可以直接修改state中的数据)
	actions:{},//定义异步方法(内部可以实行异步代码,但不能直接修改state中的数据)
	modules:{},//模块化管理state中的数据
	plugins:[]//配合其他插件管理state中的数据
4、核心api
	this.$store.commit('同步方法名',参数)
	this.$store.dispatch('异步方法名',参数)


day06

1、vuex状态管理模式的补充

1、模块化管理:用于模块化管理state中的数据,每一个模块是一个独立的js文件,每个模块有自己的state、getters、mutations、actions,最终导入一个文件,进行统一管理。
2、定义和注册模块
	//定义模块
	export default{
		namespaced:true, //让当前模块变成拥有自己独立作用域的私有模块
		state:{},getters:{},mutations:{},actions:{}
	}
	{modules:{模块名:模块}}//注册模块:
3、使用:
	//使用模块中的数据
	this.$store.state.模块名.xx
	this.$store.getters['模块名/xx']
	//使用模块中的方法
	this.$store.commit['模块名/同步方法']
	this.$store.dispatch['模块名/异步方法']


2、vuex的辅助函数

概念:用于简化在组件中使用的vuex的数据和方法
1、mapState 映射到computed中
	1)映射:不使用模块:
		computed:{...mapState(['属性1','属性2',...])}
		computed:{...mapState('模块名',['属性1','属性2',...])}
	2)使用:this.属性//和普通计算属性一样,直接调用即可
2、mapGetters 映射到computed中
	1)映射:不使用模块:
		computed:{...mapGetters(['计算方法1','计算方法2',...])}
		computed:{...mapGetters('模块名',['计算方法1','计算方法2',...])}
	2)使用:this.计算方法
3、mapMutations 映射到methods中
	1)映射:不使用模块:
		methods:{...mapMutations(['同步方法1','同步方法2',...])}
		methods:{...mapMutations('模块名',['同步方法1','同步方法2',...])}
	2)使用:this.同步方法()
4、mapActions 映射到methods中
	1)映射:不使用模块:
		methods:{...mapActions(['异步方法1','异步方法2',...])}
		methods:{...mapActions('模块名',['异步方法1','异步方法2',...])}
	2)使用:this.异步方法()


week02

1、项目准备

1、安装第三方库
	axios、element-plus、pinia-plugin-persistedstate
	其他插件:plugin-auto-import、图表库、echarts
2、路由配置:
	配实例化路由,并配置全局前置守卫、全局后置守卫
	抽离路由配置表:routerConfig.ts
	配置一级和二级路由,重定向、404、,并使用懒加载
3、网络请求:
	安装,并对axios进行二次封装:实例化axios,设置请求拦截器、响应拦截器
	统一管理应用程序的api接口:
		使用二次封装的axios实例发送请求,分模块管理请求,一个函数一个请求


2、核心功能

1、登录
	1)表单
	2)表单验证
	3)表单提交
2、面包屑
	1)封装为独立组件
	2)数据添加到pinia
	3)通过数据字典渲染
3、权限菜单的动态渲染
	1)用户的权限列表
	2)完整的菜单数据
	3)根据用户权限列表进行过滤,进行渲染
4、轮播图管理
	1)图片的增删改查
5、管理员管理
	1)管理员的增删改查
	2)新增和编辑共用一个表单,数据的回显和清空
6、产品管理
	1)产品的增删改查
7、数据可视化
	1)echarts:安装、导入、
		实例化:放在挂载后,一个实例化只能绑定一个dom节点
		绘图:ajax后拿到数据,进行绘图


你可能感兴趣的:(javascript,学习,前端,typescript,vue.js)