# Vue基础学习
**Repository Path**: wang-kangze/Vue
## Basic Information
- **Project Name**: Vue基础学习
- **Description**: 学习Vue.js基础
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 6
- **Created**: 2024-03-19
- **Last Updated**: 2024-03-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Vue基础(核心)
## **初识Vue.js**
* 想让Vue工作,就必须创建一个Vue实例,而且需要传入一个配置对象。
* root容器里面的代码依然符合HTML规范,只不过混入了一些特殊的Vue语法
* root容器里面的代码被称为Vue模板
* Vue实例和容器是一一对应的
* 真实开发中只有一个Vue实例,并会配合组件一起使用
* {{ XXX }}中的XXX要 写js表达式,且XXX可以自动读取到data中的所有属性
* 一旦data中的数据发生改变,那么页面中用到数据的地方也会自动更新
* 区分js表达式和js代码(语句)
* 表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方
* ~~~javascript
(1):a
(2):a+b
(3):demo(1)
(4):x===y ? 'a' : 'b'
~~~
* js代码(语句)
* ~~~
if(){}
for(){}
~~~
****
## **导入Vue.js**
### **Vue2.js下载**
* **开发者版本**:https://v2.cn.vuejs.org/js/vue.js 包含完整的警告和调试模式
* **生产者版本**:https://v2.cn.vuejs.org/js/vue.min.js 删除了警告,37.51KB min+gzip
### **Vue3.js下载**
* 进去后又键保存为本地文件进行导入
* **Staticfile CDN(国内)** : https://cdn.staticfile.org/vue/3.0.5/vue.global.js
* **unpkg**:https://unpkg.com/vue@next, 会保持和 npm 发布的最新的版本一致。
* **cdnjs** : https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.5/vue.global.js
* **Vue导入**
* ~~~html
~~~
****
## **模板字符串**
* **语法**
* ~~~html
{{ message }}
~~~
* **参考代码**
* ~~~html
你好,{{name}}
{{school.name}}
点击
~~~
****
## **数据绑定**
### **单向绑定**
* **语法**
* ~~~html
~~~
* 用法
* ~~~html
~~~
### 双向绑定
* **语法**
* ~~~html
~~~
* **用法**
* ~~~html
~~~
### 参考代码
* ```html
```
****
## **el与data的两种写法**
### el的写法
* **第一种**
* ~~~html
~~~
* **第二种**
* ~~~html
~~~
### data的写法
* **第一种**
* ~~~html
~~~
* **第二种**
* ~~~html
~~~
### 参考代码
* ```html
```
****
## MVVM模型
* **M:模型(Model):对应data中的数据**
* **V: 视图(View):模板**
* **VM: 视图模型(ViewModel):Vue实例对象**
* **data中所有属性,最后都出现在了vm身上**
* **vm身上的所有属性,包括Vue原型上的所有属性,在Vue模板中都可以直接使用**
* **模板字符串可以读取到vm中的所有东西 **
* **参考代码**
* ~~~html
{{ name }}
{{ address }}
~~~
****
## **数据代理**
#### 回顾Object.defineProperty方法
* **enumerable 控制是否可以被枚举(遍历),默认值为false**
* **writable 控制属性是否被修改,默认值为false**
* **configurable 控制属性是否被删除,默认值false**
* **当有人读取属性时,get(getter)就会被调用,且返回值是属性的值**
* **当有人修改属性时,set(setter)就会被调用,且会收到修改的具体值**
* **参考代码**
* ~~~html
~~~
#### **何为数据代理**
* **数据代理**:通过一个对象代理对另一个对象中属性的操作(读/写)
* 参考代码
* ~~~html
/*
修改obj1.x的值时,obj2.x的值等于obj1.x的值
*/
~~~
#### Vue中的数据代理
* 修改name时,调用set方法将data中的name修改,然后通过get方法重新渲染DOM
* 
* **getter**
* 当读取属性时,会执行get中的方法,获取到数据,并渲染页面
* **setter**
* 当修改属性时,会执行set中的方法,将修改的数据返回出去
* 
****
## **事件处理**
#### **事件的基本使用**
* **使用v-on:xxx 或者@xxx绑定事件,其中xxx是事件名**
* **事件的回调需要配置在methods对象中,最终会在vm上**
* **methods中配置的函数,不要用箭头函数,不然this就不是vm了**
* **methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象**
* **@click = "demo" 和 @click = "demo($event)" 效果一致,但后者可以传参**
#### 事件的基本使用参考代码
* ~~~html
{{ name }}
~~~
#### **事件修饰符**
* **prevent**:阻止默认事件(常用)
* ~~~html
点击
~~~
* **stop**:阻止事件冒泡(常用)
* ~~~html
~~~
* **once**:事件只触发一次(常用)
* ~~~html
~~~
* **capture**:使用事件的捕获模式
* ~~~html
~~~
* **self**:只有enent.target是当前操作的元素才触发事件
* ~~~html
~~~
* **passive**:事件的默认行为立即执行,无需等待时间回调执行完毕
* ~~~html
~~~
#### 键盘修饰符参考代码
* ~~~html
欢迎来到{{ name }}
点击
~~~
#### **键盘事件**
* **Vue中常用的按键别名**
* **回车 => enter**
* **删除 => delete(捕获“删除”和退格)**
* **退出 => esc**
* **空格 => space**
* **换行 => tap**
* **上 => up**
* **下 => dowm**
* **左 => left**
* **右 => right**
* **Vue未提供别名的按键,可以使用按键的原始的key值去绑定,但是注意要转为kebab-case(短横线命名)**
* **系统修饰见(用法特殊):ctrl、alt、shift、meta(win键)**
* **配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才能被触发**
* **配合keydowm使用:正常触发事件**
* ```HTML
```
* **也可以使用keyCode去指定具体的按键(不推荐)**
* **Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名**
#### 键盘事件参考代码
* ~~~html
{{ name }}
~~~
****
## **计算属性**
* **只要data中的值改变,模板字符串就会重新解析**
* **定义:要用的属性不存在,要通过已有属性计算得来**
* **原理:底层借助了Objcet.defineproperty方法提供getter和setter**
* **get函数什么时候执行?**
* **初次读取时会执行一次**
* **当依赖的数据发生改变时会被再次调用**
* **优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便**
* **备注**
* **计算属性最终会出现在vm上,直接读取使用即可**
* **如果计算属性要修改,那必须写set函数去响应修改,且set中要引起计算式依赖的数据发生改变**
#### 参考代码
* ~~~html
姓:
名:
{{ fullName }}
~~~
#### 计算属性简写
* ~~~xml
fullName(){
return this.fristName +'-' + this.lastName
}
~~~
****
## **监视属性**
#### 监视属性watch
* 当被监视的属性变化时,回调函数自动调用,进行相关操作
* 监视的属性必须存在,才能进行监视
* watch的Handler属性会在监视的属性发生改变时会被调用
* watch的Immediate属性为true时,handler会立即调用
* 监视的两种写法
* new Vue时传入watch属性
* ~~~html
今天的天气{{ info }}
a的值是{{ numbers.a }}
~~~
* 通过vm.$watch监视
* ```VUE
//第二种,没有确定的属性时写
vm.$watch('isHot',{
//Handler在isHot发生改变时会被调用。
handled(newValue,oldValue){
console.log(newValue,oldValue)
},
//当Immediate等于true时使handler立即执行。
immediate:true
})
```
#### **深度监视**
* Vue中的watch默认不监测对象内部值的改变(一层)
* ~~~
watch:{
isHost: {
handled(newValue,oldValue){
console.log(newValue,oldValue)
},
immediate:true
},
~~~
* 配置deep:true可以监测对象内部值的改变(多层)
* 监视多级结构中某个属性的变化
* ~~~html
'numbers.a':{
handled(newValue, oldValue) {
console.log('a改变了')
}
},
~~~
* 监视多级结构中所有属性的变化
* ~~~
numbers: {
deep:true,
handled(){
console.log('number改变了')
}
}
~~~
* Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以
* 使用watch时根据数据的具体结构,决定是否采用深度监视
#### **深度监视简写**
```html
isHost(){
console.log("这是简写方式")
}
vm.$watch('isHot',function (){
console.log('ishot被监视')
})
```
#### 参考代码
* ```html
今天的天气{{ info }}
```
****
## **watch对比computed**
* computed能完成的功能,watch都可以完成
* watch能完成的任务computer不一定能完成,例如:watch可以进行异步操作
* 两个重要的原则
* 所有被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象
* 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等),最好写成箭头函数,这样this的指向才是vm 或 组件实例对象
### 参考代码
* ```html
姓:
名:
{{ fullName }}
```
****
## **样式绑定**
#### class样式
* 写法::class="XXX" XXX可以是字符串、对象、数组
* 字符串写法适用于:类名不确定,要动态获取
* ~~~html
{{ name }}
~~~
* 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定
* ~~~html
{{ name }}
//样式对象
classObjer:{
fontSize: "40px",
color:'red',
backgroundColor:'skybule'
}
~~~
* 数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用
* ~~~html
{{ name }}
//样式数组
classArr:["happy","sad","normal"]
~~~
#### style样式
* :style ="{fontSize:XXX}" 其中XXX是动态值,指的是这个样式的值
* ~~~html
{{ name }}
styObj:{
fontSize: "40px",
color:'red',
backgroundColor:'skybule'
}
~~~
* :style="[a,b]"其中a,b是样式对象
* ~~~html
{{ name }}
styArr:[
{
fontSize: "40px",
color:'red',
backgroundColor:'skybule'
},
{
border:'1px solid stybule'
}
]
~~~
### 参考代码
* ~~~html
Title
{{ name }}
{{ name }}
{{ name }}
{{ name }}
{{ name }}
~~~
****
## **条件渲染**
* v-if
* 写法
* v-if = "表达式"
* v-else-if="表达式"
* v-else="表达式"
* 适用于:切换频率较低的场景
* 特点:不展示的DOM元素直接被移除
* 注意:v-if可以和:v-else-if、v-else一起使用,但结构要求不能被打断
* v-show
* 写法:v-show = "表达式"
* 适用于:切换频率较高的场景
* 特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
* 备注:使用v-if时,元素可能无法获取到,但是使用v-show一定可以获取到
### 参考代码
* ~~~html
当前n的值为:{{ n }}
{{ name }}
{{ name }}
{{ name }}
{{ name }}
{{ name }}
{{ name }}
{{ name }}
你好
{{ name }}
clouds
~~~
****
## **列表渲染**
### 基本列表渲染
* v-for指令
* 用于展示列表数据
* 语法:v-for="(item,index) in XXX” :key="yyy"
* 可遍历:数组、对象、字符串(少)、指定次数
* key是给节点一个标识,当key的值为index时,在dom渲染时会自动干掉,如果不写key,vue自动将key的值设为index,但是vue不知道哪个是唯一的主键
* 遍历数组
* ~~~
persons: [
{id: '001', name: 'mirage', age: '18'},
{id: '001', name: 'mirage', age: '18'}
]
~~~
* 遍历对象
* ~~~
car: {
name: 'mirage',
color: 'skybule'
},
~~~
* 遍历字符串(少)
* ~~~
str: 'hello'
~~~
* 遍历指定次数(少)
* ~~~
~~~
* 参考代码
* ~~~html
-
{{ p }}
{{ p.name }} - {{ p.id }}
-
{{ p }}
{{ p.name }} - {{ p.id }}
-
{{ value }} - {{ key }}
-
{{ char }} - {{ index }}
-
{{ a }} - {{ b }}
~~~
****
### key的原理
* **key是唯一的**
* **react、vue中的key有什么作用?(key的内部原理)**
* **虚拟DOM中的key的作用**
* key是虚拟DOM对象的标识,当状态中的数据发生变化时,V就会根据新数据生成新的虚拟DOM,随后Vue进行新虚拟DOM和旧虚拟DOM的差异进行比较
* **对比规则:**
* 旧虚拟DOM中找到了与新虚拟DOM相同的key
* 若虚拟DOM中内容没有变,直接使用之前的真实DOM
* 若虚拟DOM中的内容变了,则生成新的真实DOM,随后替换掉页面值之前的真实DOM
* 就虚拟DOM中未找到与新虚拟DOM相同的key
* 创建新的真实DOM,随后渲染到页面
* **用index作为key可能会引发的问题**
* 若对数据进行:逆序添加、逆序删除等破坏顺序操作
* 会产生没有必要的真实DOM更新 ==>界面效果没有问题,但是效率低
* 如果结构中包含着输入类DOM
* 产生错误的DOM跟训 ==> 界面有问题
* **开发中如何选择key**
* 最好使用每条数据的唯一标识作为key,如id、手机号、身份证号、学号等唯一值
* 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的
* **图解**
* 
* 
* 参考代码
* ~~~html
~~~
### 列表过滤
* 使用监视属性watch和计算属性computed两种方式进行过滤
* filter进行过滤,indexOf()功能:返回字符串中匹配子串的第一个字符的下标,indexOf中空字符串为0不为-1
* watch方式
* ~~~html
~~~
* computed方式
* ~~~html
~~~
### 列表排序
- 使用数组方法sort进行排序
- 参考代码
- ~~~html
~~~
### 模拟Vue数据监视
* 使用Observer.defineProperty对Vue的数据监视进行模仿
* 参考代码
* ~~~html
~~~
### Vue中监测数据改变的原理_对象
* 
* 参考代码
* ```html
名称:{{ student.name }}
性别:{{ student.sex }}
年龄:{{ student.age.rage }}
年龄:{{ student.age.sage }}
爱好:
{{ undefined }}
```
### Vue中的set()方法
* 第一种
* ~~~
Vue.set(位置, 添加的属性, 属性的内容)
~~~
* 参考代码
* ~~~html
名称:{{ student.name }}
性别:{{ student.sex }}
年龄:{{ student.age }}
年龄:{{ student.address }}
{{ undefined }}
~~~
* 第二种
* ~~~
this.$set(位置, 添加的属性, 属性的内容)
~~~
* 参考代码
* ~~~html
名称:{{ student.name }}
性别:{{ student.sex }}
年龄:{{ student.age }}
年龄:{{ student.address }}
{{ undefined }}
~~~
### Vue中监测数据改变的原理_数组
* 对于data中的数组,要修改需要调用数组的方法
* pust:往数组后添加东西
* pop:移除数组最后一个元素
* shift:在数组头添加东西
* unshift:删除数组的第一个元素
* splice:对数组的元素进行删除和增加
* sort:对数组进行排序,a-b是升序,b-a是降序
* reverse:反转数组中的元素
* filter:不会对数组进行修改,要用这个需要将过滤后的数组重新赋值给原数组
* Vue中的数组不是数组中的方法了,是数组原型中的方法
* 
* 参考代码
* ```html
名称:{{ student.name }}
性别:{{ student.sex }}
年龄:{{ student.age }}
爱好:
{{ undefined }}
```
### 数据监视原理总结
* Vue会监视data中所有层次的数据
* ```
data: {
student: {
name: 'mirage',
age: '19',
hobby: ['唱', '跳', 'RAP'],
friends: [
{name: 'Mirage', age: '18'},
{name: 'Clouds', age: '17'}
]
}
}
```
* 如何检测对象中的数据
* 通过setter实现监视,且要在new Vue时就传入要检测的数据
* 对象中后追加的属性,Vue不做响应式的处理
* 如需要给后添加的属性做响应式处理,请调用以下的api
* Vue.set(修改的位置,名称或者索引,内容)
* vm.$set(修改的位置,名称或者索引,内容)
* 如何检测数组中的数据
* 通过包裹数组更新元素的方法实现,本质上做了两件事:
* 调用原生对应的方法对数组进行更新
* 重新解析模板,进而更新页面
* 在Vue中更新数组一定要用如下方法
* 使用数组的api:
* push()
* pop()
* shift()
* unshift()
* splice()
* sort()
* reverse()
* Vue.set或vm.$set
* 如果要使用filter这类不会对原来的数组进行修改的,需要重新赋值给这个数组
* 特别注意:Vue.set()和vm.$set()不能给vm 或 vm根数据对象添加属性
* 参考代码
* ```html
名称:{{ student.name }}
性别:{{ student.sex }}
年龄:{{ student.age }}
爱好:
朋友
-
{{ f.name }} --- {{ f.age }}
{{ undefined }}
```
****
## 表单收集
* 若: ,则v-model收集的是value值,用户输入的就是value的值
* 若: ,则v-model收集的是value值,且要给标签配置value值
* 若:
* 没有配置value属性,则收集的是checkbox(勾选or未勾选 布尔值类型)
* 配置了value属性:
* v-model的初始值是非数组,则收集的是checkbox(勾选or未勾选 布尔值类型)
* v-model的初始值是数组,那么收集的是value组成的数组
* 备注:v-model的三个修饰符
* v-model.lazy:失去焦点时收集数据
* v-model.number:输入字符串转为有效数字
* v-model.trim:输入首位空格过滤
* 参考代码
* ```html
```
## 过滤器
* 定义:对要显示的数据进行特定的格式化后再显示(适用于一些简单的逻辑)
* 语法
* 注册过滤器Vue.filter(name,回调函数) 或 new Vue{filters:{}}
* ```
//创建全局过滤器
Vue.filter('mySlice', function (value) {
return value.slice(0, 4)
})
```
* ```html
const vm = new Vue({
el: '#root',
data: {
time: 1702028420972,
},
//过滤器实现
filters: {
//局部过滤器
timeFormater(value, str = 'YYYY-MM-DD HH:mm:ss') {
return dayjs(value).format(str)
}
}
})
```
* 使用过滤器:{{ xxx | 过滤器名 }} 或 v-bind:属性 = "xxx | 过滤器名"
* ```html
现在是{{ time | timeFormater }}
现在是{{ time | timeFormater('YYYY_MM_DD') | mySlice}}
11
```
* 备注:
* 过滤器可以接受额外的参数(第一个值是过滤器前面的值,第二个值是过滤器中括号里面传的值)
* 多个过滤器可以串联
* ```
现在是{{ time | timeFormater('YYYY_MM_DD') | mySlice}}
```
* 先执行完timeFormater的过滤器,再执行mySlice的过滤器
* 并没有改变原来的数据,是产生新的对应的数据
## 内置指令
* v-bind指令:单向绑定解析表达式,可简写为 :xxx
* v-model指令:双向数据绑定
* v-for指令:遍历数组、对象、字符串
* v-on指令:绑定事件监听,可简写为@
* v-if指令:条件渲染(动态控制节点是否存在)
* v-else指令:条件渲染(动态控制节点是否存在)
* v-show指令:条件渲染(动态控制节点是否展示)
* v-text指令:向所在的节点中渲染文本内容
* 与插值语法的区别,v-text会替换掉文本中的内容,{{xx}}则不会
* v-html指令:向指定节点中渲染包含html结构的内容
* 与插值语法区别
* v-html会替换掉节点的内容,{{xx}}则不会
* v-html会识别html结构
* 严重注意v-html有安全性的问题
* 在网站上动态渲染任意html是非常危险的,容易导致xss攻击
* 一定要在可信的内容上使用v-html,永远不要在用户提交的内容上
* v-cloak指令:(没有值)
* 本质是一个特殊的属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性
* 使用css配合v-cloak属性可以解决网速慢的时候页面展现出{{ xxx }}的问题
* ```html
{{name}}
```
* v-once指令:
* v-once节点在初次动态渲染后,就视为静态内容
* 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能
* v-pre指令:
* 跳过其所在节点的编译过程
* 可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译
## 自定义指令
* 语法总结
* 局部指令:
* ~~~
new Vue({
directives:{
指令名:配置对象
}
})
~~~
* ~~~
new Vue({
directives(){
指令名:回调
}
})
~~~
* 全局指令:
* ~~~
Vue.directive(指令名,配置对象)
~~~
* ~~~
Vue.directive(指令名,回调函数)
~~~
* 配置对象中的三个回调
* bind:指令与元素成功绑定时(一上来)调用
* inserted:指令所在元素被插入页面时调用
* updata:指令所在的模板被重新解析时调用
* 备注
* 指令定义时不加v-,但使用时要加v-
* 指令名如果是多个单词,要使用kebab-case命名方式,不要用camelCase命名
* 参考代码
* ```html
Title
、
```
* ```html
Title
当前的n值是:
放大10倍后的n值是:
```
## 生命周期
### 引出生命周期
* 又名:生命周期回调函数、生命周期函数、生命周期构子
* 是什么:Vue在关机时刻帮我们调用的一些特殊名称的函数
* 生命周期函数的名字不可以更改,但函数的具体内容是根据需求编写的
* 生命周期中的this指向的是vm或组件实例对象
* 参考代码
* ```html
Title
111
```
### 生命周期总结
* 常用生命周期钩子
* mouted:发送ajax请求、启动定时器、绑定自定义事件、订阅消息等初始化操作
* beforeDestroy:清除定时器、解绑自定义事件、取消订阅消息等
* 关于销毁Vue实例
* 销毁后借助Vue开发者工具看不到任何信息
* 销毁后自定义事件会失效,但原生Dom事件依然有效
* 一般不会再beforeDestroy操作数据,因为即使操作数据也不会触发更新流程了
* 参考代码
* ```html
Title
n的值为:{{n}}
```
****
# **Vue组件化编程**
## 非单文件组件
### 基本使用
* Vue中使用组件的三大步骤
* 定义组件(创建组件)
* 注册组件
* 使用组件(写组件标签)
* 如何定义一个组件
* 使用Vue.extend(options)创建,其中options和new Vue(options)时传入的options几乎一样,但也要些区别
* 区别如下
* el不要写,最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器
* data必须写成函数,避免组件被赋用时,素具存在引用关系
* 如何注册组件
* 局部注册:靠new Vue的时候窜如components选项
* 全局注册:靠Vue.components('组件名',组件)
* 编写组件标签
* <组件名>组件名>
* 参考代码
* ```html
Title
```
### 注意点
* 关于组件名:
* 一个单词组成
* 第一种写法(首字母小写):school
* 第二种写法(首字母大写):School
* 多个单词组成
* 第一种写法(kebab-case命名):my-school
* 第二种写法(CamelCase命名):MySchool(需要脚手架支持)
* 备注
* 组件名劲量回避HTML中已有的元素,例如h2、H2都不行
* 可以使用name配置项指定组件在开发者工具中呈现的名字
* 关于组件标签
* 第一种写法:
* 第二种写法:
* 备注:不使用脚手架时会导致后续的组件无法渲染
* 一个简写方式:
* const school = Vue.extend(options)可简写为: const school = options
* 参考代码
* ```html
Title
```
### 组件的嵌套
* 参考代码
* ```html
Title
```
### VueComponent
* 组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生产的
* 我们只需要写<组件名/>或<组件名>组件名>,Vue解析时会帮我们创建组件实例对象,即Vue帮我们执行new VueComponent(options)
* 特别注意,每次调用extend时,Vue都会为我们创建一个全新的VueComponent
* 关于this
* 组件配置中:
* data函数、methods函数、wath函数、computed函数、他们的this都是VueComponent实例对象
* new Vue(options)配置中:
* data函数、methods函数、wath函数、computed函数、他们的this都是Vue实例对象
* VueComponent实例对象,以后简称vc(也可以称为组件实例对象)
* Vue实例对象,以后简称vm
* 参考代码
* ```html
Title
```
### 一个重要的内置关系
* 一个重要的内置关系:VueComponent.prototype.__ _proto_ _ _ === Vue.prototype
* 为什么要有这个关系:让组件实例对象(VueComponent)能够访问到Vue原型对象上的属性、方法
## 单文件组件
* Vue 的单文件组件 (即 *.vue 文件,英文 Single-File Component,简称 SFC) 是一种**特殊的文件格式,使我们能够将一个 Vue 组件的模板、逻辑与样式封装在单个文件中**。
* 参考代码
* ```vue
{{ name }}
```
* 外部文件导入
* 参考代码
* ```vue
```
****
# 使用Vue脚手架
## 初始化脚手架
* 全局安装脚手架@vue/cil
* ~~~
npm install -g @vue/cil
~~~
* **切换到需要创建项目的目录**,使用命令创建脚手架
* ~~~
cd 目录位置
~~~
* ~~~
vue create xxx
~~~
* 启动项目
* ~~~
run npm serve
~~~
* 备注
* 如果下载慢,可以配置使用淘宝镜像
* ~~~
npm config set registy https://registry.npm.taobao.org
~~~
* 脚手架隐藏了所有webpack配置,若要查看具体的webpack配置,请执行
* ~~~vue
vue inspect > output.js
~~~
## VueCli文件解析
* .gitignore:git忽略文件,不需要上传git仓库的在这个文件里面写好
* babel.config.js:babel的配置文件
* babel:es6语法转es5语法
* babel的中文文档:https://babel.nodejs.cn/docs
* package.json:包含了包名、常用短命令、包的版本
* serve:在本地启动项目
* build:生产版本,代码完成后执行的编译
* lint:代码检查(不常用)
* package-lock.json:包含了包的版本信息、包的下载地址、包的node.js版本
* version:包的版本
* resolved:包的下载地址
* integrity:用来验证资源的完整性,即是否是我期望加载的资源,而不是被别人篡改了内容
* dependencies:当前包的生产依赖树
* devDependencies:当前包的生产依赖
* engines:node.js的版本
* readme.md:项目的介绍|教程
* **src**:
* main.js:项目的主入口文件,在这里创建Vue实例对象
* render函数:
* 在创建Vue实例的位置没有使用render函数+$mount进行挂着会导致报错
* ~~~
You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
翻译为: 您使用的是 Vue 的仅运行时构建,在该构建中模板编译器不可用。要么将模板预编译为render函数,要么使用包含编译器的构建。
~~~
* 原因是导入的Vue.js不是完整版的Vue.js而是vue.runtime.esm
* 使用es6语法引入Vue的方式只是引用了Vue的文件,具体引用了哪个Vue是靠Vue文件架下面的package包中module的来控制,默认dist/vue.runtime.esm.js
* esm指的是在es6语法下默认的模块
* vue.runtime.esm.js默认没有模板解析器
* 完整版的VUE是vue目录下dist中的vue.js文件
* 只要render函数
* rander函数传参:
* createElement:元素名、元素内容
* rander必须要有返回值
* rander简写:
* render:函数名=>函数名(参数)
* vue版本区别:node_modules下vue文件下dist文件
* vue.js与vue.runtime.xxx.js的区别
* vue.js是完整版本的Vue,包含:核心功能+模板解析器
* vue.runtime.xxx.js是运行版的Vue,只包含核心功能,不包含模板解析器
* 因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接收到的createElement函数去指定具体内容
* 只有在main.js中才使用rander函数
* App.vue:所有组件的父组件
* components:存放子组件的位置
* assets:存放静态资源的位置
* **public**:
* favicon.ico:网页的图标位置
* index.html:项目的主文件,项目最终会运行在这个文件上
* ```html
<%= htmlWebpackPlugin.options.title %>
```
* node_modules:第三方依赖包
* output.js:被脚手架隐藏的webpack配置项,里面包含了VueCli的webpack配置,在这个文件里面更并不奏效,这个文件只是输出出来给我们看的
* 使用vue inspect > output.js就可以查看vue脚手架默认配置
* vue脚手架中哪些文件不能更改:
* public文件下的内容不能更改,但是可以被同名文件替换
* src文件名字不能更改
* main.js名字不能更改
* 对vue脚手架进行个性化定制:package同文件下创建vue.config.js
* vue.config.js(可选择是否使用,如不使用则使用默认配置):
* 配置项查询连接:https://cli.vuejs.org/zh/config/#vue-config-js
* 使用的暴露方式:
* ```
module.exports = defineConfig({
})
```
* 参考代码:
* main.js:
* ```
/*
* 该文件是整个项目的入口文件
* */
//引入Vue
import Vue from 'vue'
// 引入App组件,它是所有组件的父组件
import App from "@/App.vue";
// 关闭vue的开发者提示
Vue.config.productionTip = false
// 创建Vue的实例对象
new Vue({
render: h => h(App),
// render(createElement, hack) {
// return createElement('h1', '你好啊')
// }
}).$mount('#app')
```
* App.vue:
* ```
```
* School:
* ```vue
{{ name }}
```
* Student:
* ```
{{ name }}
```
* vue.config.js:
* ```
const {defineConfig} = require('@vue/cli-service')
module.exports = defineConfig({
//转es5语法时忽略node_modules
transpileDependencies: true,
// 停止代码检查
lintOnSave: false
})
```
## ref属性
* 用来给元素或子组件注册引用信息(id的替代者)
* 应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
* 使用方法:
* 标识:
* ~~~
<组件名字 ref="" />
~~~
* ~~~
~~~
* 获取方式:this.$refs.xxx
* 参考代码:
* App.vue:
* ```
```
* School:
* ```
{{ school }}
```
## prope配置项
* 功能:让组件接受外部传过来的数据
* 传递数据:
* 传递字符串方式
* ~~~
~~~
* 传递其他类型
* ~~~
~~~
* 接收数据:
* 第一种接收方式(只接收):
* ~~~
props:['name']
~~~
* 第二种方式(限制类型):
* ~~~
props:{
name:String
}
~~~
* 第三种方式(限制类型、限制必要性、指定默认值)
* ~~~
props:{
type:String,//类型
required:true,//必要性
default:'老王'//默认值
}
~~~
* 备注:
* props是只读的,Vue底层会检测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data值的数据。
* 参考代码
* App.vue:
* ```
```
* School:
* ```
{{ school }}
{{ my_age }}
{{ sex }}
```
## mixin(混入)
* 功能:可以把多个组件的共用配置提取成一个混入对象
* 使用方式:
* 第一步定义混合
* ~~~
{
data(){…………},
methods:{},
……
}
~~~
* 第二步使用混入,例如:
* 全局混入:
* ~~~
Vue.mixin(xxx)
~~~
* 局部混入:
* ~~~
mixin:[xxx]
~~~
* 参考代码:
* main.js:
* ~~~
/*
* 该文件是整个项目的入口文件
* */
//引入Vue
import Vue from 'vue'
// 引入App组件,它是所有组件的父组件
import App from "@/App.vue";
// 导入混合文件并全局配置混合
import {mixin} from "../mixin";
Vue.mixin(mixin)
// 关闭vue的开发者提示
Vue.config.productionTip = false
// 创建Vue的实例对象
new Vue({
render: h => h(App),
}).$mount('#app')
~~~
* School.vue
* ~~~
学校名称{{ name }}
学校{{ school }}
~~~
* mixin.js:
* ~~~
export const mixin = {
methods:{
showName() {
alert(this.name)
}
}
}
~~~
## Vue插件
* 功能:用于增强Vue
* 本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据
* 定义插件:
* ~~~
对象.install = function(Vue,options){
//1.添加全局过滤器
Vue.filter(……)
//2.添加全局指令
Vue.directive(……)
//3.配置全局混入
Vue.mixin(……)
//4.添加实例方法
Vue.prototype.$myHethod = function(){……}
Vue.prototype.$myProperty = xxx
}
~~~
* 使用插件:
* ~~~
Vue.use(插件名字)
~~~
## scoped样式
* 作用:让样式在局部生效,防止冲突
* 写法:
* ~~~