# Vue_basic **Repository Path**: wangxiaoshuaishuai/vue_basic ## Basic Information - **Project Name**: Vue_basic - **Description**: 保存一些vue相关练习和资料 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2021-09-27 - **Last Updated**: 2025-01-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: Vue, vue基础 ## README # Vue-basic-note ### vue初体验总结 ##### 关于初体验控制台的提示信息 ```js // 提示信息一: Download the Vue Devtools extension for a better development experience: https://github.com/vuejs/vue-devtools // 大概理解为: 缺少 Vue Devtools扩展工具 需要下载 // 解决方法: // 在谷歌的商店安装 Vue Devtools扩展工具 // 提示信息二: You are running Vue in development mode. Make sure to turn on production mode when deploying for production. See more tips at https://vuejs.org/guide/deployment.html // 大概理解为: 在vue 启动时生成生产提示 // 解决方法: // 阻止 vue 在启动时生成生产提示 Vue.config.productionTip = false; ``` ##### 总结 1.想让Vue工作,就必须创建一个Vue实例对象,且必须传入一个配置对象。`new Vue({})` 2.demo容器中的代码,依然符合html规范,只不过其中混入了一些特殊的Vue语法。 3.demo容器中的html代码+Vue语法,我们称之为Vue模板。 ### vue 注意点 几个注意点: 1.Vue实例和容器是一一对应的,真实开发中一定只有一个Vue实例,且真实开发中会配合组件一起使用。 2.data中的数据只要发生改变,模板中用到该数据的地方,就会自动更新。 3.{{xxx}}中的xxx要写js表达式,且xxx可以直接读取到data中配置的所有属性。 4.简单理解表达式:可以产生一个值 如果可以使用**const x = 表达式** 接收 来判断是否为表达式 注意区分【js表达式】与【js语句(代码)】 1.表达式:会产生一个值,可以放在任何一个需要值的地方 (1).100 (2).a (3).demo() (4).x === y ? 1 : 0 (5). 200 - 2 (6). arr.map() 2.语句(代码): 不会产生值,只是控制代码走向 (1). if(){} (2). for(){} (3). try{} catch(err){} 等等..... ##### 分析实例对象 ```js //创建一个Vue实例对象 new Vue({ el:'#demo', //el的值可以是:css选择器字符串(用的多)、写一个真实的DOM元素(几乎不用) data:{ //data用于配置数据,数据供el所指定的容器去使用,data的值暂时先写成一个对象 name:'尚硅谷', address:'宏福科技园', person:{ name:'tom', age:13 } } }) ``` ### 模板语法 Vue中的模板语法有2大类: 1.插值语法(胡子语法): 功能:用于解析标签体内容(不能用于解析标签属性) 写法:**{{xxx}}**,xxx是js表达式,且可以自动读取到data中的所有属性 2.指令语法: 功能:用于解析标签(标签属性、标签体、绑定事件........) 举例:v-bind:href = "xxx" 或简写为 :href = "xxx" xxx同样要写js表达式 v-bind: 这个必须懂 **: v-bind:的简写** 这个必须会 以后常用 备注1:Vue中有很多指令,且形式都是v-???,此处我们只是拿v-bind举个例子。 备注2:只有v-bind指令,才能简写为:,别的指令不行。 备注3:别的指令,有别的简写方式,但并不是所有的指令都有简写方式。 ### 数据绑定 ##### 两种数据绑定方式: 1.单向数据绑定(v-bind):数据只能从data流向页面。 ```js 单向数据绑定(v-bind):
单向数据绑定(v-bind):
``` 2.双向数据绑定(v-model):数据不仅能从data流向页面,也能从页面流回data ```js 双向数据绑定(v-model):
双向数据绑定(v-model):
``` **备注1**:v-model只能应用在表单元素上(输入类元素) 备注2:v-model默认只收集元素的value值,所以v-model:value="xxx" 可以简写成 v-model="xxx" ### MVVM MVVM模型: 1. M:模型(Model) :对应data中的数据 2. V:视图(View) :模板 3. VM:视图模型(ViewModel) : Vue实例对象 观察发现: 1.vm身上有很多$开头的属性或方法,这些属性或方法一般都是给我们程序员用的(也不都用)。 2.data中配置的属性,最后都出现在了vm身上。 3.vm身上所有的属性,以及Vue.prototype中的属性,在模板中都可以直接使用。 ### el和data两种写法 ##### el的两种写法 ```js //el的第一种写法——借助el配置项 new Vue({ el:'#demo', data:{ name:'尚硅谷' } }) //el的第二种写法——借助vm.$mount(选择器) const vm = new Vue({ data:{ name:'尚硅谷' } }) vm.$mount('#demo') ``` ##### data的两种写法 ```js //data的第一种写法—— 对象式 new Vue({ el:'#demo', data:{ name:'尚硅谷' } }) //data的第二种写法—— 函数式,现阶段我们可以把data直接写成一个对象,但学到了组件后,data就必须是一个函数了! new Vue({ el:'#demo', data(){ console.log(this) //data函数必须写成普通函数,这样其中的this才是vm return { name:'尚硅谷' } } }) ``` ##### 关于el和data两种写法的总结 1.el有2种写法 (1).第一种: new Vue时候配置el属性(css选择器字符串 或 亲自获取的DOM元素)。 (2).第二种: 先创建Vue实例,随后再通过:vm.$mount('#demo')指定服务的容器。 (3).用哪一种呢?随意,只不过第二种更灵活一点 例如:可以在Vue实例对象创建n秒以后,再指定容器。 2.data有2种写法 (1).第一种对象式: data:{name:'尚硅谷'} (2).第二种函数式: data(){ return { name:'尚硅谷' } } 如何选择? 目前哪种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。 3.一个重要的原则: 由Vue管理的函数(现阶段我们只学了个data函数,别的没学呢), 一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。 ### vue 数据代理 1.前情提要: 我们new Vue(options)时传入的那个data,被Vue收到了,放在了vm上名为_data。 2.Vue中的数据代理: 通过vm对象来对_data中属性的操作(读/写) 2.Vue中的数据代理: 通过vm对象来代理对_data中属性的操作(读/写) 3.**面试题** Vue中数据代理的好处:(或者也可以说为什么要使用数据代理) 模板中可以更加方便的操作_data中的数据,例如: (1).若无数据代理:{{_data.name}} (2).若有数据代理:{{name}} ———————— 香!!! 4.基本原理: 遍历_data对象中所有的属性,通过Object.defineProperty()一个一个都添加到vm上。 随后vm上就拥有了_data中所有的属性,且都有自己的getter/setter。 getter/setter内部操作(读/写)的是_data中对应的属性。 ### 事件处理 ##### 事件绑定 1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名,原生有的DOM事件都可以写; 2.事件的回调函数需要配置在methods中; 3.methdos中的函数最终也会出现在vm上(但不存在数据代理了,是直接放在vm上的); 4.methods中配置的函数,是Vue所管理的函数,所以务必要写成普通函数; ###### 两种写法 ```js ``` ###### 事件对象 事件对象: `` 当我们点击button时,Vue会帮我们调用showMsg,并且会自动传入当前的事件对象。 ##### 事件传参 1.不传参数,那就写:@click="showMsg" ,showMsg会收到一个event 2.传一个参数,那就写:@click="showMsg(6)" ,showMsg会收到一个6 3.传多个参数,那就写:@click="showMsg(6,7,8)" ,showMsg会收到:6、7、8 4.传参同时还想用事件对象,那就写:@click="showMsg($event,6)",showMsg会收到:事件对象、6 5.注意:传参时,当然也可以传递data中的数据,例如@click="showMsg(name)" ##### 事件修饰符 ```js 重要的事件修饰符: 1.prevent:阻止默认事件; 2.stop:阻止事件冒泡; 3.once:事件只触发一次; 不常用的事件修饰符: 1.capture:使用事件的捕获模式 2.self:只有event.target是当前操作的元素时才触发事件 3.passive:事件的默认行为立即执行 无需等待事件回调执行完毕 备注:事件修饰符,可以串联 ``` ##### 键盘事件 ```js 1.Vue中常用的按键别名(牢牢掌握): 回车 => enter 删除 => delete (捕获“删除”和“退格”键) 退出 => esc 空格 => space 换行 => tab(必须配 合keydown才有效果) 上 => up 下 => down 左 => left 右 => right 2.备注:也可以使用keyCode去指定具体的按键(不太推荐) ``` ### 计算属性 * 提到计算属性 就应该想到**智能** **缓存** ##### 计算属性标准写法 ```js 计算属性: 1.定义:要用的属性(数据)不存在,要计算得来。 2.原理:底层通过Objcet.defineproperty实现的。 3.关于get何时调用? get函数何时调用? (1).初次读取fullName时会执行一次。 (2).当计算fullName所依赖的数据发生改变时会被再次调用。 set函数(setter)何时调用?—— 只有一个时候:当计算属性被直接修改的时。 4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,且调试方便。 5.备注: (1).计算属性最终会出现在vm上,在模板中可直接使用即可 (2).如果计算属性后期要被直接修改,那必须写set函数(setter)去响应修改。 ``` 代码示例: ```js computed:{ //声明一个计算属性,名为:fullName,值得看get函数(getter)调用的返回值 fullName:{ //get函数(getter)何时会被调用?—— 1.Vue初次解析模板的时候(模板中得用)2.当该计算属性所依赖的数据发生变化时候 get(){ console.log('fullName-get') //解构赋值,从vm中读取:姓、名 const {firstName,lastName} = this return firstName[0].toUpperCase() + firstName.slice(1) + '-' + lastName }, set(val){ const arr = val.split('-') this.firstName = arr[0].toLowerCase() this.lastName = arr[1] } } } ``` ##### 计算属性的简单写法 * **前提**是 当计算不被修改时(不用setter时),才能简写 代码如下: ```js computed:{ fullName(){ //解构赋值,从vm中读取:姓、名 const {firstName,lastName} = this return firstName[0].toUpperCase() + firstName.slice(1) + '-' + lastName } } ``` ### 监视属性watch 1.当被监视的属性变化时, 回调函数自动调用, 进行相关操作 2.监视的属性必须存在,才能进行监视!! 3.监视的两种写法: (1).new Vue时传入watch配置 (2).通过vm.$watch监视(了解即可) 备注:被监视的可以是:属性(data),也可以是计算属性(computed) ```js ``` ##### 立即监视 立即监视: 1.配置:immediate:true 2.作用:可以让数据没有发生变化时,Vue初次工作时就执行一次监视的回调 ```js watch:{ isHot:{ immediate:true, // 这里是否需要开启立即监视 handler(newValue,oldValue){ console.log('isHot的值发生变化了~~~',newValue,oldValue) } } } ``` ##### 深度监视 深度监视: (1).watch默认不监测对象内部值的改变(监视一层)。 (2).配置deep:true可以监测对象内部值改变(监视多层)。 备注: (1).Vue自身可以监测对象内部值的改变(无论多深都可以),但Vue给程序员提供的watch默认不可以! (2).使用watch时根据数据的具体结构,以及需求,决定是否采用深度监视。 ```js watch:{ //监视某个对象中某个属性的变化 /* 'age.foreignAge':{ handler(){ console.log('foreignAge被改变了') } }, */ //监视某个对象的改变(地址值),不监测对象中属性的改变 /* age:{ handler(){ console.log('age被改了') } } */ //监视某个对象的改变(地址值),且也可以监视到对象中属性的改变 age:{ deep:true, //开启深度监视 handler(){ console.log('age被改了 或 age中的某个属性改了') } } } ``` ##### 监视属性的标准写法和简写 ```js watch:{ //标准写法 /* isHot:{ handler(value){ if(value) this.url = './imgs/re.jpg' else this.url = './imgs/cool.jpg' } } */ //简写 isHot(value){ if(value) this.url = './imgs/re.jpg' else this.url = './imgs/cool.jpg' } } ``` ### computed计算属性和watch监视属性的总结(面试相关) ```txt computed和watch之间的区别: 1.computed能完成的功能,watch都可以完成。 2.watch能完成的功能,computed不一定能完成,最具代表性的:watch可以进行异步操作。 computed: (1).侧重在【算】,核心是:计算出来的值。 (2).靠return来输出计算的结果。 (3).不能开启异步任务。 watch: (1).侧重在【监视】,核心是:xxx变了,我要做???事。 (2).无需return,靠内部逻辑去完成要做的事。 (3).可以开启异步任务。 两个重要的原则: 1.所被Vue管理的函数,要写成普通函数,这样this的指向才是vm 或 组件实例对象。 2.所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数), 要写成箭头函数,这样this的指向才是vm 或 组件实例对象。 ``` ### 绑定样式 绑定class样式 写法为: :class="xxx" xxx可以是字符串、对象、数组。 (1).字符串写法适用于:要绑定的样式,类名不确定。 (2).对象写法适用于:要绑定的样式,个数确定,类名也确定,但不确定用不用。 (3).数组写法适用于:要绑定的样式,个数不确定、类名也不确定。 ### 条件指令 v-if 写法: (1).v-if="表达式" (2).v-else-if="表达式" (3).v-else 适用于:切换频率较低的场景。 特点:不展示的DOM元素直接被移除。 注意1:v-if可以和:v-else-if、v-else一起使用,但要求结构不能被“打断”。 注意2:如果使用v-if,可能会出现无法获取元素的问题。 v-show 写法:v-show="表达式" 适用于:切换频率较高的场景。 特点:不展示的DOM元素依然在,仅仅是使用样式隐藏掉 ### 数据代理与数据劫持(面试相关) 数据代理: 1.目的:让程序员更加方便的读取到_data中属性; 2.原理:Object.defineProperty; 3.体现:vm身上有每一个属性的proxyGetter、proxySetter; 4.当修改vm上的属性时,该属性对应的proxySetter就会调用,去修改_data中对应的属性; 5.当读取vm上的属性时,该属性对应的proxyGetter就会调用,去读取_data中对应的属性; 数据劫持(_data里的那点事): 1.目的:为了捕获到数据的改变,进而重新解析模板; 2.原理:Object.defineProperty; 3.体现:_data身上的每一个属性不直接给值,而是都有对应的:reactiveSetter、reactiveGetter; 4.当修改_data上的属性时,该属性对应的reactiveSetter就会调用; 且在reactiveSetter中Vue会:更新数据、重新解析模板; 5.当读取_data上的属性时,该属性对应的reactiveGetter就会调用,返回对应的值;