vue学习

这里写目录标题

  • Vue2 介绍
  • vue 单向数据流
  • 数据双向绑定v-model
  • vue数据响应式
    • vue2
    • vue3
  • 数据驱动视图——MVVM
    • MVC
    • 原理
  • vue渲染过程
    • $mount:挂载定义好的模板
    • Vnode:虚拟dom,用js去描述一个dom
    • path:虚拟dom的核心,可以把vnode渲染成真实dom,diff算法
    • 虚拟dom
    • diff算法
  • vue2使用script引入
  • 使用
    • 差值绑定
    • 逻辑v-if,v-else-if,v-else
    • 显示隐藏 v-show
    • 循环:v-for
    • 事件
    • style scope
  • 2.下载脚手架
    • (1)国内镜像
      • 查看npm原地址,改成淘宝镜像
    • (2)全局包,局部包,依赖包
    • (3) vue --version(查看vue版本)
    • (4)查看电脑中全局安装的所有包,保证有@vue
    • (5)卸载npm uninstall -g @vue/cli
    • (6)全局安装@vue/cli
    • (7)判断是否安装成功
    • (8)创建vue项目
      • (8.1)vue create 名字(不能有中文)
      • (8.2)选择预设
      • (8.3) 从备选项中选择特性
      • (8.4)Choose a version of Vue.js选择Vue版本
      • (8.5) Use history mode for router是否使用history路由
      • (8.6) Pick a CSS pre-processor选择CSS预处理
      • (8.7) Pick a linter / formatter config选择纠错/格式化配置
      • (8.8) Pick additional lint features什么时候纠错
      • (8.9) Where do you prefer placing config for Babel, ESLint, etc. Babel和ESLint的配置存放在哪里
      • (8.10) Save this as a preset for future projects前面的配置项是否存起来,以后复用,N
  • 文件构成
    • 单文件组件 1.vue
      • data必须为函数
  • 事件
  • v-if
  • v-for
    • v-for和v-if的优先级
    • 优化computed
  • v-model
    • 原理
    • 表单修饰符
    • 事件修饰符
    • 按键修饰符
    • 鼠标修饰符
    • v-bind修饰符
    • 如果不用v-model如何绑定数据
    • 组件v-model+inpu v-model
      • 字符串
      • 对象
    • 单输入框使用v-model
    • 单个多选框使用v-model,一个值true/false
    • 多个多选框v-model 数据是数组
    • select 下拉列表使用v-model
  • 计算属性computed
    • get和set
    • 新闻列表搜索
    • 计算属性传值, return一个 function
  • 监听器watch
    • 1.简单监听
    • 2.复杂监听
    • 如何监听多个值的变化?watch+computed
  • computed和watch的区别
  • 节流防抖用在什么地方
  • 过滤器filter
    • 基本使用
    • 全局定义
    • 传值
  • data数据
    • 重置data数据
  • 组件component
    • 全局组件main.js
    • 局部组件
    • 组件之间通信总结
      • 父——>子
      • 子——>父
      • 兄弟——>兄弟(eventBus/eventHub)
      • eventbus原理
      • $parent和 $refs实现通信
      • $children
      • vuex任意组件通信
    • 组件的v-model
    • 插槽slot
      • 默认插槽
      • 具名插槽
      • 作用域插槽
    • 动态组件component is:
    • 封装过的公共组件
  • $实例系列
    • vm.$el
      • 获取当前组件的template的根标签
      • 父子组件的$el
    • vm.$data
    • vm.$options
    • vm.$refs
      • ref加在普通元素上
      • .ref加在子组件上
    • $ parent和$ children
    • vm.$nextTick
    • vm.$emit( eventName, […args] )
    • $ attrs (v-bind="$ attrs":父组件传过来的属性,props没有接收就会在$attrs中显示 )
  • 生命周期
    • 父子组件生命周期执行顺序
      • 父子组件加载渲染数据过程
      • 父子组件更新渲染数据过程
      • 父子组件销毁组件数据过程
      • 不同页面跳转时各页面生命周期
  • 路由
    • 路由原理
      • H5 提供的pushState(data, title, targetURL) 和 replaceState(data, title, targetURL)
    • vue中使用
      • 下载去看官网
    • 原生js获得hash路由传参参数
    • vue-router的hash模式和history模式
    • 路由跳转的方式
      • 声明式导航
      • 编程式导航
    • 传递参数
      • 传递query参数
      • 传递params参数
      • query和params区别
      • 传递props参数
    • 编程式路由
    • 历史记录操作模式push,replace模式
    • router/index.js配置
    • 二级路由
    • $ router和$ route
      • $ router API
      • $ route API
    • 路由高亮
      • 1.使用类名,router-link-active或则router-link-exact-active
      • 2.使用active-class
    • < router-link>API
    • 路由的滚动行为,
    • < keep-alive>
      • 切换路由上使用( 缓存路由)
      • activated 激活,路由独有生命周期,用于捕获路由组件的激活状态
      • deactivated 失活,路由独有生命周期
      • 动态组件上使用
    • 路由守卫(权限设置)
      • 执行顺序
      • 全局前置路由守卫beforeEach
      • 全局后置路由守卫afterEach
      • 独享路由守卫
      • 组件内路由守卫
      • router.addRoute()动态添加路由
      • resetRouter 重置路由
      • router.matcher (负责route匹配)
      • router.addRoute(动态添加路由)
      • $route.fullPath(当前页面路由的完整地址,用于请求接口后的重新渲染)
      • router.removeRoute()动态删除路由
    • 页面刷新的几种方法
    • 路由切换不刷新的解决方法
    • router-view的key属性
    • 404路由
  • axios
    • 1.下载
    • post
    • get
    • 组合用法
    • 并发请求
    • 创建实例create使用axios
    • 多个并发请求
    • 拦截器
      • 请求拦截器
      • 响应拦截器
    • main.js里全局配置 axios
    • 封装axios 见另一个博客
    • proxy 跨域
    • qs
  • vue 动画
    • 1.transition想让谁产生动画就用transition标签包起来
    • 2.用@keyframes+.v-enter-active写
    • 3.用vue的动画写
      • 初始延时2秒出现动画
    • 4.多个元素过渡transition-group
    • 5. 使用Animate.css
      • 1.安装
      • 2.引入
      • 3.使用
  • vuex
    • actions和mutaions的区别
    • modules模块化使用
      • 1.引入
      • 2.使用
    • actions向后端发送请求
    • mapstate用法
    • mapGettters
    • mapMutations
    • mapactions
    • 实现持久化存储
  • vue原型上挂个方法
  • vue定义全局变量的方法
    • 1.Vue.prototype
      • 1.1Vue.prototype定义插件
      • 1.2 Vue.use()初始化插件
      • 1.3 二者的区别
    • 2.全局变量的定义还可以通过在main.js中new Vue,支持修改
    • 3.通过vuex定义全局变量
  • 混入 mixin
    • 混入和vuex的区别
    • 缺点
    • 混入冲突规则
      • (1)生命周期函数
      • (2)data数据
      • (3)方法
    • 1.定义
    • 2.引入
      • 局部引入
      • 全局引入
  • 自定义指令directive+inserted
    • binding.value() 执行绑定的函数
    • 钩子函数
    • 钩子函数参数
    • 动态参数
  • 自定义插件install
    • 创建js对象
  • vue打包(webpack)
    • 打包空白页
    • 1.做项目的时候考虑过浏览器兼容性吗
    • 2.关闭map文件
    • 3.public静态资源和assets
    • 4.vue 优化—— cdn
      • CDN优化(cdn引入第三方资源包)
      • cdn引用
      • 静态资源放到cdn上
      • cdn静态资源刷新 /预热
    • gzip压缩
    • 5.publicPath:'./' 公共路径前缀,打包后的
    • 6. 环境变量区分开发环境和生产环境
    • 7.css后处理postCss
    • 8.开启本地服务器
      • 1.方式一
      • 2.方式二
    • 上线流程
  • 配置环境变量
      • 1.创建文件
      • 2.配置
      • 3.来到 package.json 文件夹找到scripts 利用 --mode 来分配我们项目跑起来的指令分别对应的是生产模式开发模式
      • 4.只需要判断是什么环境在请求的时候用哪个路径就可以
      • 5.用js来判断变量
  • vue源码
    • 模板解析
    • vue生命周期
    • vue源码添加事件
    • 数据劫持
    • v-model
  • 单页面打包成多页面
    • 1、SSR服务器渲染
      • vue项目重构ssr
      • 使用nuxt.js创建项目
    • 2、预渲染模式
  • !!!!!! vue3 !!!!!!
    • 和v2区别
    • 安装
      • 1.使用vue2方式创建
      • 2.使用vite创建
      • webpack和vite的区别
      • ts的项目中使用js
      • main.js
    • v3组合式API
    • setup
      • ref 函数
      • reactive函数
      • ref和reactive的区别
      • setup可以收到2个参数 setup(props, context)
    • components 组件
    • ts+组合式api +数据
    • 获得html标签的ref
    • 父——>子组件传值ts+defineProps
      • withDefaults用来给defineProps的props 提供默认值的方式
    • 子——>父组件传值ts+defineEmits
    • 简单defineProps和defineEmits
    • 子——>父ref + defineExpose(暴露组件自己的属性 )
    • 祖——>孙provide和inject 祖孙组件通信
      • 祖——>孙provide/inject的ts,v3用法
    • 计算属性computed
    • watch 监听
      • 1.watch监听ref
      • 2.watch监听reactive
      • 3.watchEffect
      • watchEffect+ts
      • 4.watch监听defineProps传递数据
    • v3生命周期
      • 通过配置项在setup外面配置
      • 组合式API生命周期
      • ts+组合式api的生命周期
    • hook函数——复用js部分相当于mixin
      • 1.创建hooks文件夹
      • 2.定义
      • 3.引入
    • 组件上使用v-model
      • 父子组件for循环修改绑定v-model
    • 其他配置
      • 1.toRef()和toRefs()
      • 2.shallowReactive和ShallowRef(浅响应)
      • 3.readonly和shallowReadonly
      • 4.toRaw 和 markRow转普通对象
      • 5.customRef 自定义ref
    • 响应式数据判断
    • 自定义指令
    • 新的组件
      • Fragment
      • Teleport
      • Suspense
      • defineAsyncComponent()异步引入组件
    • vue3 的其他变化
      • 全局api转移
      • 动画类名修改
      • 移出keyCode作为v-on的修饰符,不再支持config.keyCodes
      • v3 移除 @click.native 事件修饰符
      • 移除filter
    • v3 路由
      • 全局路由守卫
      • 路由独享守卫
      • 组件内路由 onBeforeRouteLeave,onBeforeRouteUpdate
      • 监听路由router变化
      • 路由懒加载
    • mitt.js 替代EventBus
      • 1.安装:$ npm install --save mitt
      • 2.定义
      • 3.使用
    • Transition 动画
      • 路由切换动画
      • JavaScript 钩子
    • TransitionGroup:用于对 v-for 列表中的元素或组件的插入、移除和顺序改变添加动画效果。
    • app.config.globalProperties 定义一个全局使用的方法
  • TS
    • ts 新增类型
      • 联合类型 : number|null
      • 元组:是一种特殊的数组
      • type 类型别名,给其他类型起别名
      • 声明接口:interface 描述对象的属性
      • interface 和type的区别
      • 字面量类型
      • 枚举:enum
      • void
      • any 任意的。当类型设置为 any 时,就取消了类型的限制
    • 类型断言
      • <类型>值
      • as写法
      • ?可选参数
      • 非空断言 !
      • 泛型 T 值<类型>
      • event 事件类型(去取input元素的value值的时候会报错)
      • 转 as Ref< string>类型
    • any和unknow区别
    • 强制转换类型
    • ts报错
      • ts 对象可能为“未定义”。
      • Typescript: type‘string’|‘undefined’类型不能赋值给type‘string
    • 高级类型
      • 1.交叉类型
      • 2.联合类型
      • 3.type 类型别名
      • 4.类型保护as断言
      • 5.null和undefined
    • 装饰器@expression
    • 在项目中的使用
  • Pinia
    • 和vuex区别
    • 1.下载
    • 2.定义
    • 3.页面使用
      • state获取/修改
      • actions
      • getters
      • mainStore.$reset()重置
      • 跨容器调用
    • 4.持久化 pinia-plugin-persist插件

Vue2 介绍

Vue2 不支持 IE8 及以下版本Vue3 不支持 IE11 及以下版本,兼容ie就别用vue3了因为 Vue 使用了 IE8 无法模拟的 ECMAScript 5 特性(Object.defineProperty())。但它支持所有兼容 ECMAScript 5 的浏览器。
Vue是构造函数 使用new创建,是一套用于构建用户界面的渐进式框架。
渐进式代表的含义是:主张最少。我们可以简单的理解为,用自己想用或者能用的功能特性,不想用的部分功能可以先不用。VUE不强求你一次性接受并使用它的全部功能特性。

vue 单向数据流

props emit不能直接修改父级的数据,vuex不能直接修改数据,直接修改会报错(引用类型不会)
在开发中如果有多个子组件依赖与父组件的某个数据,万一子组件真的可以直接修改父组件的数据,那么一个子组件的变化将会引发所有依赖于这个数据的子组件的变化,

数据双向绑定v-model

数据双向绑定和响应式不要搞混
数据和视图相互驱动更新,是相互影响的关系

双向数据绑定通常是指我们使用的v-model指令的实现,是Vue的一个特性,也可以说是一个input事件和value的语法糖。

```javascript
  <input
    :value="age"
    @input="age = $event.target.value"
  />

vue数据响应式

Vue采用的是数据劫持结合发布和-订阅者模式的方式,通过拦截对数据的操作,在数据变动时发 布消息给订阅者,触发相应的监听回调。

vue2

VUE2.0 通过 Object.defineProperty 来劫持对象属性
Vue对数组的7个变异方法(push、pop、shift、unshift、splice、sort、reverse)实现了响应式

缺点
1.Vue 无法检测 property 的添加或移除——通过Vue.set(vm.someObject, ‘b’, 2),或者 this. $ set(原数组, 索引值, 需要赋的值) this.$set(this.arr, 0, “老李”);
2.无法检测数组更改例如 a[1]=0;——同上方法Vue.set(vm.items, indexOfItem, newValue)
3.不能在data里面增加项——初始时写入data,值为空
4.不能检测数组和对象的变化

    // 假如node是遍历到的input节点
    node.addEventListener("input",function(e){
        vm.name=e.target.value;
    })  

2.通过defineProperty来监听每一个属性给input赋值

    Object.defineProperty(data,"name",{
        get(){
            return data["name"];
        },
        set(newVal){
            let val=data["name"];
            if (val===newVal){
                return;
            }
            data["name"]=newVal;
            // 监听到了属性值的变化,假如node是其对应的input节点
            node.value=newVal;
        }    
    })

vue3

VUE3.0 通过 Proxy直接可以劫持整个对象,并返回一个新对象,我们可以只操作新的对象达到响应式目的

let obj = {
    a: 1,
    b: 2
}
const proxy = new Proxy(obj, {
    get: function(target, prop, receiver) {
        return prop in target ? target[prop] : 0
    },
    set: function(target, prop, value, receiver) {
        target[prop] = 666
    }
})
console.log(proxy.a) // 1
console.log(proxy.c) // 0
proxy.a = 10
console.log(proxy.a) // 666
obj.b = 10
console.log(proxy.b) // 不是666 而是10 

数据驱动视图——MVVM

是一种软件架构模式,是MVC的改进版,MVVM将其中View的状态和行为抽象化,让我们将视图的UI和业务上的逻辑进行分开。简单来说,MVVM是Model-View-ViewModel的简写。即是模型-视图-视图模型。
【model 模型】指的是后端传递的数据。

【view 视图】指的是所看到的页面,亦可以理解为将数据以某种方式呈现给用户

【Viewmodel 视图模型】mvvm模式的核心,它是连接view和model的桥梁

ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,不需要手动操作DOM,就可以完成更新
MVVM与MVC最大的区别就是:它实现了View和Model的自动同步

MVC

MVC 是Model-View-Controller的缩写,即模型-视图-控制器。
MVC是单向通信。也就是View跟Model,必须通过Controller来承上启下。

Model:后端传递的数据;
View:展示出来的页面;
Controller:业务逻辑。

MVC 是单向通信,即 View 和 Model,必须通过 Controller 来进行控制。使用 MVC 的目的就是将 Model 和 View 代码分离。

  1. View 传送指令到 Controller;
  2. Controller 完成业务逻辑后要求 Model 改变状态;
  3. Model 将新的数据发送到 View,用户得到反馈。

原理

Vue数据驱动,就是利用Object.defineProperty或Proxy,将属性全部转为 getter/setter。
同时每一个实例对象都有一个watcher实例对象,用getter去访问data的属性,watcher此时就会把用到的data属性记为依赖,这样就建立了视图与数据之间的联系。
当之后我们渲染视图的数据依赖发生改变(即数据的setter被调用)的时候,watcher会对比前后两个的数值是否发生变化,然后确定是否通知视图进行重新渲染。

vue渲染过程

  1. new Vue 执行初始化
  2. 挂载$mount方法,通过自定义render,template生成render函数
  3. 使用watch监听数据变化
  4. 当数据改变的时候,render函数执行生成vnode对象
  5. 通过path方法对比新旧vnode,diff算法更新

$mount:挂载定义好的模板

new Vue({el:"#app"})
||
var app=new Vue({}).$mount("#app")

Vnode:虚拟dom,用js去描述一个dom

render函数调用creatElement方法,对子节点进行规范生成vnode,然后调用vm._update方法,执行path函数,把vnode渲染到真实dom上

path:虚拟dom的核心,可以把vnode渲染成真实dom,diff算法

虚拟dom

就是将真实的dom节点用JavaScript来模拟出来

diff算法

添加key 可以提升性能,判断是不是同一个节点

  1. 如果不是一个节点,就删除旧的,插入新的
  2. 如果是一个节点(div),就比较children
    (2.1)如果新旧都没有children,就直接替换
    (2.2)如果新旧都有children,判断文字节点一样吗,不一样就代表有新元素了,就添加
    (2.3)新的有children,旧的没有children,添加进去

v2使用递归+双指针双端比较算法,
v3使用最长递增子序列,通过比较更新后的最长序列,如果递增就代表不用变化子序列元素

vue2使用script引入

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>

使用

差值绑定

1.文本:{{}}

 <div id="box">
 	{{text}}
    </div>
    
 const Vm = new Vue({
        el: '#box',
        data: {
            text: "Hello", 
        },
    })

2.属性:v-bind:class=“name” name不是变量就需要加‘name’

 <div id="box">
     <button :disabled="true">按钮</button>//disabled后面需要跟布尔类型的值
 	  <div :style="'color:'+colorText+';'">111111</div>//需要字符串拼接
    </div>
    
 const Vm = new Vue({
        el: '#box',
        data: {
            colorText: "pink", 
        },
    })

class,style的绑定

数组语法:<p :class="['red','big']">{{msg}}</p>:会依次将'red''big'解析到class里面
对象语法:<p :class="{red:true,'big':isBig}">{{msg}}</p>:键值对的值为true,则将对应的属性名添加到class,为false则不添加

3.直接绑定html:v-html=“span”

<div id="box">
 	<div v-html="text"></div>
</div>
    
 const Vm = new Vue({
        el: '#box',
        data: {
            text: '1111111', 
        },
    })

逻辑v-if,v-else-if,v-else

<div id="box">
	 <button :disabled="num>=100" @click="num++">按钮</button>//超过100就不可以点击了
        {{num}}
        <div v-if="num>=80">优秀</div>
        <div v-else-if="num<=80&&num>=60">及格</div>
        <div v-else="num<60">不及格</div>
</div>
    
 const Vm = new Vue({
        el: '#box',
        data: {
            num: 45, 
        },
    })

显示隐藏 v-show

<div id="app">
<div v-show="false">显示/隐藏</div>//等于dispaly=“none”
</div>

循环:v-for

<div id="app">

  <div v-for="(item,index) in list" :key="index"> {{item}}-{{index+1}}</div>

</div>

var app = new Vue({
  el: '#app',
  data: {
    list: ['苹果', '香蕉', '菠萝']
  }
})

事件

style scope

当使用ellementui的时候样式问题,覆盖不住,就可以添加deep属性

2.下载脚手架

(1)国内镜像

npmjs是国外的,下载速度会很慢
镜像把npmjs的所有包,全部复制到国内的服务中,保持同步
npm install 安装包的时候,可以将原始的国外源改成国内的镜像,下载安装会更快

查看npm原地址,改成淘宝镜像

npm config get registry
查看npm原地址

npm config set registry https://registry.npmmirror.com/
改成淘宝镜像

在这里插入图片描述

(2)全局包,局部包,依赖包

全局包:所有路径都可以直接使用
局部包:在哪安装,只能在哪用,在某一个项目中使用
依赖包:一个包依赖多个包

(3) vue --version(查看vue版本)

(4)查看电脑中全局安装的所有包,保证有@vue

npm ls -g --depth=0

vue学习_第1张图片

(5)卸载npm uninstall -g @vue/cli

(6)全局安装@vue/cli

找到文件夹,右键管理员打开
npm install -g @vue/cli
vue学习_第2张图片

(7)判断是否安装成功

vue --version
在这里插入图片描述

(8)创建vue项目

(8.1)vue create 名字(不能有中文)

进入文件夹cmd
vue create 名字(不能有中文)

(8.2)选择预设

vue学习_第3张图片

  • v3
  • v2
  • 手动选择

(8.3) 从备选项中选择特性

vue学习_第4张图片

项目 Value
Babel 根据项目运行环境针对性的转义es6
TypeScript js 的超集,给js添加强类型约束
Progressive Web App (PWA) Support 渐进式网络
Router 路由
Vuex 状态管理(统一数据管理)
CSS Pre-processors css预处理(sass/scss/less)
Linter / Formatter 纠错/代码格式化
Unit Testing 单元测试
E2E Testing 端对端测试

(8.4)Choose a version of Vue.js选择Vue版本

2.x

(8.5) Use history mode for router是否使用history路由

n

(8.6) Pick a CSS pre-processor选择CSS预处理

Sass/SCSS (with dart-sass)

(8.7) Pick a linter / formatter config选择纠错/格式化配置

选择第一个( ESLint with error prevention only )

ESLint with error prevention only 仅语法或者vue规定纠错
ESLint + Airbnb config 使用Airbnb 公司配置纠错
ESLint + Standard config 使用推荐标准配置纠错
ESLint + Prettier纠错+代码格式化

(8.8) Pick additional lint features什么时候纠错

◉ Lint on save
◯ Lint and fix on commit

(8.9) Where do you prefer placing config for Babel, ESLint, etc. Babel和ESLint的配置存放在哪里

❯ In dedicated config files单独的文件中
In package.json

(8.10) Save this as a preset for future projects前面的配置项是否存起来,以后复用,N

vue学习_第5张图片

文件构成

vue学习_第6张图片
vue学习_第7张图片

单文件组件 1.vue

data必须为函数

防止产生数据污染。initData时会将其作为工厂函数都会返回全新data对象,操作数据不会影响其他实例,
这也就意味着如果你的data是一个普通的对象,那么所有复用这个实例的组件都将引用同一份数据,这就造成了数据污染!

//安装插件后可以用快捷键vbase
<template>//只可以包一个标签
<div class="home"> <h1>{{num}}</h1> <button @click="add">按钮</button> </div> </template> <script> //单文件组件的script中,需要导出默认对象 export default { name: 'HomeView', data() {//以函数的方法书写 return { num: 1 } }, methods: { add(){ this.num++ } } } </script> <style lang="sass" scoped> </style>

事件

v-on:click=“my”
@click=“my”

v-if

<div v-if="true">

v-for

<template v-for="(item,index) in arr" :key="item.id">
{{item.name}}
</template>

v-for和v-if的优先级

vue2 vue3
v-for > v-if v-if > v-for
不建议一起使用因为每个循环都要判断if ,消耗性能 因为v-if优先级在前,会消失掉,v3中可以< template v-for=“i in arr” :key =“i.id”>< div v-if=“i.name”>< /template>

优化computed

<ul><li
    v-for="user in activeUsers"
    :key="user.id"
  > {{ user.name }} </li></ul>
computed: {
  activeUsers: function () {
    return this.users.filter(function (user) {
      return user.isActive
    })
  }
}

v-model

v-model是双向绑定,给表单项插值绑定一个变量,当用户操作这个表单项时,会自动将该变量做同步(修改变量)

原理

v-bind+@input见下面例子

表单修饰符

项目 Value
lazy 在change
trim $1600
number $1600
<!--  lazy修饰符:使得用户在输入数据之后,当数据失去焦点或点击回车时,才会进行数据的更新-->
  <input type="text" v-model.lazy="message">
  <h2>用户输入的内容: {{message}}</h2>
<!--  number修饰符:将用户输入的类型由string型转为number型-->
  <input type="number" v-model.number="num">
  <h2>{{num}}: {{typeof num}}</h2>
  <!--  trim修饰符:将用户输入的文本信息中开头的空格,结尾的空格都删除-->
  <input type="text" v-model.trim="name">
  <h2>用户输入的内容: {{name}}</h2>

事件修饰符

1.prevent:阻止默认事件(常用)
​ 2.stop:阻止事件冒泡(常用)
​ 3.once:事件只触发一次(常用)
​ 4.capture:使用事件的捕获模式
​ 5.self:只有 event.target 是当前操作的元素时才触发事件
​ 6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕

按键修饰符

@keyup.entry=“my”

项目 Value
.entry 当key是entry时候
.esc 当key是esc的时候

鼠标修饰符

<button @click.left="shout(1)">ok</button>//左
<button @click.right="shout(1)">ok</button>//zhon
<button @click.middle="shout(1)">ok</button>

v-bind修饰符

能对props进行一个双向绑定

//父组件
<comp :myMessage.sync="bar"></comp> 
//子组件
this.$emit('update:myMessage',params);

相当于下面的写法

//父亲组件
<comp :myMessage="bar" @update:myMessage="func"></comp>
func(e){
 this.bar = e;
}
//子组件js
func2(){
  this.$emit('update:myMessage',params);
}

如果不用v-model如何绑定数据

  <input
    :value="age"
    @input="age = $event.target.value"
  />

组件v-model+inpu v-model

字符串

//a.vue引入b.vue(是input组件)
   <item-git v-model="inp"></item-git>
 inp: "123",
//b.vue
<input :value="value" @input="$emit('input', $event.target.value)" />
 props: {
        value: {
            type: String,
        },
    },

对象

//b.vue
  <input :value="value.age" @input=" $emit('input', { age: $event.target.value, name: value.name })  "  />
  <input  :value="value.name" @input=" $emit('input', { name: $event.target.value, age: value.age })  " />
   props: {
        value: {
            type: Object,
        },
    },
 <item-git v-model="inp"></item-git>
     inp: { age: 19, name: "张三" },

单输入框使用v-model

<input v-model="age" />

data() {
    return {
      age: 16,
    };

单个多选框使用v-model,一个值true/false

//如果勾选中对钩则点击按钮可以点击
  <input
    type="checkbox"
    v-model="checked"
  />
  <a href="./#/about">用户协议</a>
  <button :disabled="!checked">提交注册</button>
data() {
    return {
      checked: true,
    };
  },

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

多个多选框v-model 数据是数组

<label>
    <input
      type="checkbox"
      value="A"
      v-model="aList"
    >A. JSONP
  </label>
  <label>
    <input
      type="checkbox"
      value="B"
      v-model="aList"
    >B. 服务器代理
  </label>
  
 data() {
    return {
      aList: ['A'],//默认选中A
      //选中添加到数组里
    };

select 下拉列表使用v-model

//默认选中sh
 <select v-model="city">
    <option value="bj">北京</option>
    <option value="sh">上海</option>
    <option value="gz">广州</option>
  </select>

   data() {
    return {
      city: 'sh'
    };

计算属性computed

根据依赖关系进行缓存的计算,只有在它的相关依赖发生改变时才会进行更新
比如搜索数据,拖动排序 使用vuex,不能直接修改component,使用computed的get和set

//验证表单数据 ,满足条件才可提交
<input v-model="formData.phone" placeholder="手机号" />
  <input v-model="formData.code" placeholder="验证码" />
  <button :disabled="isSubmitDisabled">登陆</button>
  
  computed: {
    isSubmitDisabled() {
      return !/^1\d{10}$/.test(this.formData.phone) || !/^[0-9]{4}$/.test(this.formData.code);
    }
  },

get和set

默认只有 getter,可以设置set

<button @click="onchangName">按钮修改值</button>
        {{changName}}

		 data() {
            return {
               name:'李四'
            }
        },
        methods: {
          onchangName(){
            this.changName='张三'//点击按钮后执行set之后还会在执行一次get
            //所以控制台一开始打印1 
            //点击按钮后打印2,1
          }
        },
        computed: {
            changName: {
                get(){ console.log(1)
                    return this.name
                },
                set(val){ console.log(2)
                    this.name=val
                }
            }
        },

新闻列表搜索

searchList(){
                if(this.keyword){
                    return this.list.filter(i=>{ return i.includes(this.keyword)})
                }else{
                    return this.list
                }
                
            }

计算属性传值, return一个 function

const comp = computed((a, b) => {
  return function (a: number, b: number) {
    return a + b
  }
})

监听器watch

监听data中的数据 当data中的数据改变的时候 watch就会触发
也可以监听一个计算属性变化,购物车商品结算的时候,动态获取数据,一开始还没数据监听数据变化

watch在vue中是一个单独的配置项
watch中的函数名称必须和属性名称一致,且不能人为调用
没有返回值,如需使用处理结果,必须将结果赋值给data中的成员再进行使用

1.简单监听

<input type="text" v-model="name"/>
 data(){
    return {
      name: ""
    }
  },
 
 watch: {
    name(newValue, oldValue) {//新值和旧值
      
    }
  },

2.复杂监听

watch只会监听数据的值是否发生改变,而不会监听地址的变化,如果需要监听引用类型的数据变化,需要深度监听:obj:{handler(newVal){},deep:true}------用handler+deep的方式进行深度监听。
在特殊的情况下(更改数组中的数据时,数组已经更改,但是视图没有更新),watch无法监听数组的变化,更改数组必须要用splice()或者$set。
immediate: true, // 立即执行
immediate会让watch执行顺序提升至created之前,这个可是坑点,如果你在immediate中修改了初始data值,就会导致created获取的值是修改过的值,导致一些人瞬间懵逼。
deep: true, // 深度侦听复杂类型内变化

<template>
  <div>
    <input type="text" v-model="user.name">
    <input type="text" v-model="user.age">
  </div>
</template>
 
<script>
export default {
  data(){
    return {
      user: {
        name: "",
        age: 0
      }
    }
  },
  // 目标: 侦听对象
  watch: {
        // 第一种:监听整个对象,对象里的每个属性值的变化都会执行handler
        // 注意:属性值发生变化后,handler执行后获取的 newVal 值和 oldVal 值是一样的
    user: {
      handler(newVal, oldVal){
        console.log(newVal, oldVal);
      },
      deep: true,
      immediate: true
    }
  }
// 目标: 精确侦听对象中的某个值
 watch: {
       // 第二种方式:监听对象的某个属性,被监听的属性值发生变化就会执行函数
       // 函数执行后,获取的 newVal 值和 oldVal 值不一样
    'user.name': {
      handler(newVal, oldVal){
        console.log(newVal, oldVal);
      },
      deep: true,
      immediate: true
    }
  }
}
</script>

如何监听多个值的变化?watch+computed

data() {
    return {
       password:"",
       userCode:""
    }
},
computed: {
   info() {
      const { password, userCode } = this
      return {
          password,
          userCode
      }
   },
},
watch:{
    info:{
       handler: function(newval , oldval) {
          if(newval.password && newval.userCode){
            this.sign = true
          }else{
            this.sign = false
          }
       },
       deep:true
   },
}

computed和watch的区别

computed watch
计算的内容需要依赖多个属性的情况 计算的内容依赖一个属性的情况
监听值未在data中定义,以return返回值形式; 监听值要在data中先定义,可以不写return返回值;
计算属性的值会被缓存,只有实例中相关依赖值改变时,才重新计算,性能好但不适合做异步请求; 不支持缓存,可以做异步操作;
计算属性默认只有get来读取,手动修改计算属性时,会触发手写的set函数。 监听值改变,回调函数自动调用。
项目应用:(1)平均分,(2)总价,(3)成功/失败文字的切换,(4)拖动组件(Vue.Draggable)的时候使用vuex的数据不允许直接修改state,使用computed的get和set处理 处理异步传进来props的数据问题,监听路由$router变化,搜索数据筛选

节流防抖用在什么地方

防抖:输入框的搜索功能 ,页面resize事件,提交按钮
节流:scroll 事件

过滤器filter

vue中的过滤器可以用在两个地方:双花括号插值和 v-bind 表达式
平时开发中,需要用到过滤器的地方有很多,比如单位转换、数字打点、文本格式化、时间格式化之类的等,
比如我们要实现将30000 => 30,000,这时候我们就需要使用过滤器

vue学习_第8张图片

基本使用

在这里插入图片描述

全局定义

vue学习_第9张图片

传值

在这里插入图片描述
filterA收到message的值,处理完成后的值传到filterB

{{name|newFilter('---')}}//张三---

name:'张三',

 newFilter: function(value,str) {
                return value+str;
            }

data数据

重置data数据

  Object.assign(this._data, this.$options.data());
//  this.$options.data()执行完成后,返回初始化data数据,赋值给data

组件component

views里面放路由组件,components里面放非路由组件

全局组件main.js

所有组件都可以使用,自己也可以调用自己

import ModalBox from './components/ModalBox.vue'

Vue.component('modal-box',ModalBox)//全局定义   参数一组件名,参数二组件定义

局部组件

A.vue
B.vue
B引到A里面
1.在A页面引入B组件 import Bvue from ‘./B.vue’;
2.在components中挂载组件
3.在页面中使用

//A.vue
<template>
  <div class="home">    
    <Bvue></Bvue>//3.页面中使用
  </div>
</template>

<script>
//单文件组件的script中,需要导出默认对象
import Bvue from './B.vue';//1.引入组件
export default {
  components: {//2.挂载组件
    Bvue,//相当于Bvue:Bvue
  },
}
</script>

组件之间通信总结

props / $emit (vue2)父组件通过 props 向子组件传递数据,子组件通过 $emit 和父组件通信
defineProps/defineEmits (vue3)写法
子defineExpose——>父ref (vue3)暴露子组件的方法属性
$ emit/$on vue2 eventBus
mitt.js vue3的eventBus(Vue3 从实例中完全删除了 $ on、$off 和 $once 方法)
v-model 语法糖
slot 插槽
vuex 全局事件总线
pinia vue3
provide/inject v3 多用于祖孙通信(祖传孙)依赖注入
$ parent/$children 与 ref 通过父链 / 子链也可以通信
插槽 父子组件通信作用域插槽

父——>子

通过自定义属性,子组件用过props接收

//父
<modal-box :show="showModal" > </modal-box>

//子
  props: {//不允许修改组件的props,vue是单向数据流,如果要修改,只能派发一个自定义事件,让父组件改
            show: {
                type: Boolean,
                default: false,
                require:true,//必传项
                 //如果是对象默认值default:()=>({}),
                 //数组 default: () => []
        },}

 props:['show'],//简写方式

如果子组件没有声明props 会在$attrs身上

如果是对象默认值default:()=>({}),
props 默认值需要函数返回原因和data是一样的吧。多个父组件引用同一个子组件时,引用类型 props 要相互隔离。

子——>父

通过自定义事件,子组件通过 this.$emit(‘close’,num1,num2)

//父
<modal-box @close="showModal=false" ></modal-box>

//子
<button @click="onClose">X</button>


methods: {
            onClose(num1,num2) {
                this.$emit('close')
            }
        },

兄弟——>兄弟(eventBus/eventHub)

1, main.js中定义实例

//main.js
//利用公共组件实例上的$on 和$emit通信
//在已经创建好的Vue实例原型中创建一个EventBus
Vue.prototype.$EventBus = new Vue()   
//使用a.vue 发送
 methods: {
    sendMsg() {
      /*调用全局Vue实例中的$EventBus事件总线中的$emit属性,发送事
      件"aMsg",并携带A组件中的Msg*/
      this.$EventBus.$emit("aMsg", '123');
    }
  }


//b.vue 接收
 mounted() {
    /*调用全局Vue实例中的$EventBus事件总线中的$on属性,监听A组件发送
    到事件总线中的aMsg事件*/
    this.$EventBus.$on("aMsg", (data) => {
      //将A组件传递过来的参数data赋值给msgB
      this.search(data)
    });
  }
    methods:{
        search(data){console.log(data)}
    }
  //需要解绑
 beforeDestroy() {
    this.$EventBus.$off("abc", this.search);
  },

v3移出了 官方移除 $ on、$ off 和 $once 方法 需要使用第三方库
mitt
tiny-emitter添加链接描述

eventbus原理

利用的发布订阅,$on订阅消息, $emit发布消息

class EventBus {
    constructor() {
        this.eventObj = {}
    }
//注册事件(订阅)
    on(eventName, cb) {//第一个参数是事件名,第二个是回调函数
        if(this.eventObj[eventName]) {
            // 如果事件存在则push进去
            this.eventObj[eventName].push(cb)
        } else {
           // 不存在则新建一个数组存储
            this.eventObj[eventName] = [cb]
        }
    }
// 触发事件(发布) 
    emit(eventName, ...params) {//第一个参数是事件名,后面的都是参数
        if(!this.eventObj[eventName]){
            console.log('事件不存在')
        } else {
            this.eventObj[eventName].map(cb => {
                cb(...params)//添加到数组里面,并且执行
            })
        }
    }
 
     off(eventName) {
        if(this.eventObj[eventName]){
            delete this.eventObj[eventName]
        }
    }
}
 
const eventBus = new EventBus()
export default eventBus

$parent和 $refs实现通信

ref获取某一子组件
$parent 获取当前组件父组件,可以操作父组件的数据和方法

//a.vue获取
this.$parent.$refs.list.listArr//[{},{}...]
//父.vue
 <b ref="list"></b>//需要定义ref才可以找到

$children

获取当前组件下的所有子组件,返回数组

//item.vue
<a-view/>
<b-view/>
this.$children//a和b组件的实例

vuex任意组件通信

//a.vue发送到vuex
this.$store.commit('setFormData', JSON.parse(JSON.stringify(this.formData)));
//store/index.js
   setFormData(state, formData) {
      state.formData = formData;
    }
//b.vue监听vuex里面的数据变化,拿到数据
watch: {
     '$store.state.formData'() {
      this.pageNo = 1;
      this.getList();
    }
  },

组件的v-model

组件的v-model 是当子组件满足props是value 抛出事件叫input 同时要同步更新value 就可以用v-model
子组件进行操作更改父组件的一个值的时候用到

//父
	<start-list @input="star=$event" :value="star"></start-list>
        <!-- 下面这句是上面的语法糖 -->
     <start-list v-model="star"></start-list>
//子
<li v-for="item in 5" :key="item" 
                :class="{'active':item<=value)}"
                @click="$emit('input',item)"//抛出事件input
            >
                
            </li>
 props: {
            value: {//传入value
                type: Number,
                default: 3
            }
        },

插槽slot

组件的子标签

默认插槽

<slot></slot>

具名插槽

//注意 v-slot 只能添加在 < template> 上

//父
<Left>
   //