![[welcome-to-vue.png]] ### Vue基本认知 **Vue是一个JavaScript框架,它的特点在于使用者不用再思考DOM的操作,一切都由Vue来承担,这就是Vue的MVVM模式,使用Vue框架你只需要操作数据而不是DOM。** Vue的v-for: 是Vue中一个简单的for循环,目前学到的课程中它可以用来遍历数组。 Vue的v-on: 是Vue中用于绑定事件的指令,它的作用是绑定一个事件,它可以简写成@。 Vue的v-bind: 用于传递数据,它可以帮你在组件之中传递值。 Vue的v-model: 数据的双向绑定。 Vue的el: 是Vue实例的“管辖范围”,它用于确定Vue实例的生效区域。 Vue的data: 是Vue实例的数据区域,它一般用于放置Vue实例中的数据内容。 Vue的methods: 用于放置Vue实例的方法,任何Vue中的使用的函数方法都要在其中定义。 ### Vue 的深入理解 #### Vue的组件间传值 需要用到`props`、`v-bind`、`$emit`等方法的配合。 ##### Vue的生命周期函数 Vue在实例生成之前和生成之后总共有8个生命周期函数,他们分别是: * `beforeCreate`:在实例生成之前 * `created`:实例生成之后 * `beforeMount`:实例渲染之前 * `mounted`:实例渲染之后 * `beforeUpdata`:实例数据修改之前 * `updatad`:实例数据修改之后 * `beforeDestroy`:实例销毁之前 * `destroyed`:实例销毁之后 #### Vue的模板语法 Vue中的模板语法有插值表达式、`v-text`、`v-html`等等。 任何v-开头的Vue指令,后面接的都是JS的表达式,也就是说可以在后面接上加减乘除等JS语句,插值表达式也是如此。 #### 计算属性,方法和侦听器 ##### 计算属性 ```computed```: 直接通过属性名就能使用,因为原因和上面说的一样: >任何v-开头的Vue指令,后面接的都是JS的表达式。也就是说可以在后面接上加减乘除等JS语句。 > 缓存功能在计算的成员值不变的情况下将不会进行第二次计算,节省资源。 ##### 方法methods: 也可以直接通过属性名使用(注意方法独有的括号),但是它没有计算属性的缓存功能,在计算成员值不变的情况下每次都会重新计算一次,在网页元素比较多的情况下可能会有比较明显的资源浪费。 ##### 监听器watch: 可以监听指定的方法,当监听的方法发生变化时会执行指定的操作,保留了计算属性的缓存功能。 当以上三种方法同是适用的候,优先推荐计算属性 `computed`,既简洁,也保留了性能。 #### 计算属性的getter和setter 计算属性你可以使用 `Get`方法,通过其他值算出一个新值,也可以使用 `Set`方法,通过设置一个值改变相关联的值,从而使用计算属性的特性引起第二次计算。 #### Vue中的样式绑定 可以使用 `isActivated`来控制样式名字的显示和隐藏,在 `data` 或 `methods` 中设置 `isActivated` 为true就会绑定上CSS的样式。也可以使用数组来控制样式名字,设置数组的第一个值为空,标签就没有绑定CSS样式,设置数组第一个值为CSS样式名字则会绑定,还可以使用`V-bind:style="CSS样式名字"`的方式来进行绑定,这样CSS样式名字就是一个Vue的 `data` 值,可以在Vue的`data` 中控制它的属性,以此类推,这种方法后面也能接一个数组,更多样化。 #### Vue的条件渲染 ##### v-if、v-else-if、v-else: `v-if`是一个Vue的指令,它的值决定了它所在的这个DIV标签是否渲染显示,每次的隐藏和显示都相当于删除和增加一个DOM元素,它还能搭配 `v-else` 或 `v-else-if`一起组合使用(警告,`v-if` 和 `v-else`、`v-else-if`必须紧靠在一起使用!)。 由于Vue的特性,Vue在渲染网页的时候会尽量复用页面上已有的DOM,这可能会产生一些问题,为了解决这些问题就有`key`值这个概念,`key`值是独一无二的,Vue并不会复用key值不一样的DOM元素。 ##### v-show: `v-show` 与 `v-if`类似,但是它每次的隐藏和显示并非是在页面上删除和增加一个新的DOM,而是通过隐藏DOM标签,在相同的环境下,`v-show`所需要的性能相对要低于前者。 #### Vue的列表循环 ##### key、数组操作: 当使用`v-for`遍历来实现列表渲染编写`key`值时,考虑到性能和一些未知的问题,尽量不要使用数组的下标作为`key`值,而是使用数组中一些独一无二的值。 当你直接对Vue的数组操作其下标时,数据会发生变化,但是页面不会发生变化,你需要使用Vue提供的7个数组操作方法来对数组进行操作,它们分别是: * `push`:向数组的末尾添加一个元素 * `pop`:删除数组的最后一个元素 * `shift`:删除数组的第一个元素 * `unshift`:向数组的开头添加一个或多个元素 * `splice`: 向数组中删除或添加元素 * `sort`: 对数组进行排序 * `reverse` 对数组进行取反 还有通过改变数组的引用来实现对数据的操作,即直接改变遍历的数组,这种方法也能在数据变化的同时页面同时变化 ##### 遍历对象: 列表渲染不但可以使用数组,也可以使用一个对象,使用的方式和数组相同,但是使用对象进行列表渲染时,网页并不会渲染对象的键名,而是直接显示对象的值,取而代替的是一个叫`key`的变量,其中对象的`index`和数组相同。 在使用对象进行列表渲染时,你无法使用Vue提供的7个数组操作方法,你可以直接修改对象里的数据,数组变的同时页面也会跟着发生变化,但是和数字相同:直接往对象里添加数据时,页面是不会发生变化,与之类似,你可以直接改变对象的引用来实现数据的变化页面跟着变。 #### 使用组件的细节点 当你使用Vue的组件功能实现组件化时,你定义了一个组件,这个组件的名字可能与HTML自有的标准不符,使用这些组件的时候会产生一些问题,这时Vue提供了 `is="组件名"` 的语法来解决这种问题,这种方法的作用就是在遵守HTML标准的同时使用你自定义的组件。 在组件中定义`data` 时,`data` 必须是一个函数而不是一个对象。 ##### ref: 当你在HTML标签中使用ref时,你获取到的是 `ref` 对应标签的DOM元素,而当你在组件中使用 `ref` 时,你获取到的是子组件的引用。 #### 父子组件传值 ##### 隐形的规定——单向数据流: 父组件可以随意的向子组件传值,子组件也可以修改父组件传递过来的值,但是这样可能会导致一些问题,所以在子组件中使用父组件传递来的值时,需要使用子组件自己的 `data` 来复制一份来自父组件的值。 ##### emit(): 子组件向父组件传值需要用的 `$emit()` 这个方法,这个方法不但可以向外触发事件,还可以在触发事件的同时传递一个值(向外触发的事件名可能不允许大写)。 #### 组件参数校验与非props特性 ##### 参数校验: 父组件可以任意向子组件传值,子组件对传递过来的值可以进行一个校验,也就是对传递的值有一定的约束,要使用这个特性,子组件里的props就不再是一个数组,而是一个对象,在对象中可以对传递过来的值进行一个约束,约束的条件还可以是一个数组,甚至是一个对象。 当 `props` 是一个对象时,你可以使用 `validator` 这一个函数还对传递值进行校验,还可以使用 `default` 来规定一个未传值时的默认值,required来规定父组件必须传值,当然还有 `type` 来约束传递的值类型。 ##### 非props特性: 当父组件向子组件传值的时候,子组件需要声明 `props` 来获取来自父组件的值,这个时候父组件传递的值并不会显示在子组件DOM中,但是子组件如果并没有声明 `props` 来获取父组件的值,那么这个值会显示在子组件的DOM中,这就是 `非props` 特性。 ##### 给组件绑定原生事件 当你直接在子组件的中使用父组件的函数,这时候绑定的其实是组件的自定义事件,需要用 `$emit` 来向外触发和监听,你需要在子组件中的模板中绑定这个事件,这时候绑定和触发的才会是父组件的函数,如果你确实需要直接用子组件绑定父组件的事件,你可以在子组件的自定义事件后面添加 `.native`,这个时候绑定的也是父组件的函数。 #### 非父子组件间的传值 ##### bus: 在使用Vue进行组件化传值的时候,会遇到这样一个问题:非父子组件间传值。如果按照传统的方法将值一层一层传递上去,这样写出来的代码将会非常冗长,这是就有了 `bus`这个概念,在使用 `bus`前你需要事先给 `Vue.prototype.bus`赋值一个新的Vue实例: `Vue.prototype.bus = new Vue()`,这句话的意思在 `Vue.prototype`上挂载了一个名叫 `bus`的属性,它指向一个Vue的实例。每当你去创建一个Vue实例或者一个组件时,都会有bus这个属性。 有了 `bus`,非父子组件间传值就变的非常容易了,就像子组件向父组件传值那样,传值组件中用 `bus`向外触发一个事件:`this.bus.$emit("事件名","数据")`。然后在Vue的8个生命周期钩子之一:`mounted`(实例渲染之后)中写一个函数,这个函数 `bus`中的 `$on`函数监听 `bus`向外触发的事件名和数据,再传递给接收组件。这样就完成了非父子组件间传值的需要。(警告:在接受组件的 `mounted`函数中操作数据时,`this`的作用域可能会发生变化,需要用 `var this_ = this`来保存 `this`的数据。) #### 在Vue中使用插槽 ##### 插槽: 子组件内的某些元素需要由来自父组件或者其他组件的值来决定时,子组件自带的模板似乎就不是那么好用,这时Vue就提供了一个新的功能:插槽。插槽使用的方法很简单,只需要在子组件的模板中添加一行要插入的内容,之后在 `template`中相应的位置插入 ``就可以了,在这个元素中还可以加入默认值以表示插槽未定义时的值。 ##### 具名插槽v-slot: 假如你需要由来自两个不同的组件的值来显示在不同的插槽位置时,单单``是不够的,为了解决这个问题,Vue有一个新的指令 `v-slot`,它用于给插槽指定一个名字,之后在 `template`使用`name="插槽名"`就可以实现不同位置显示不同的插槽的需求。(注意:`v-slot`只能写在模板占位符即 `template`中) ##### 作用域插槽slot_sope: 组件化的使用过程中还有可能遇到一种情况:当子组件的 DOM结构应该由外部传递进来的时候,这个时候就要使用作用域插槽来解决问题,子组件插槽可以向父组件插槽传数据,子组件用 `v-bind`传,父组件用 `slot-scope="属性名"`接受数据。 #### 动态组件与v-once指令 ##### 动态组件: 在之前的笔记中可以看到:在一个 DOM元素中使用 `is="组件名"`的方式可以在不影响语法要求的情况下将原来的DOM元素替换为定义的组件,这种特性与``结合就成了Vue的动态组件(也可以不是``),在 `data`中定义一个变量,变量的值是组件名,通过改变这个变量的名为其他组件名来实现动态组件。 ##### v-once: 在上面的方法每当 `is="组件名"`的值变化,在渲染显示一个组件的同时,Vue会将其他的未被渲染的组件隐藏销毁,也就是说用上面的方法每次动态组件切换时Vue就会渲染组件的同时和销毁隐藏的组件,如果频繁切换组件这种方法无疑会影响性能,`v-once`指令会将组件在隐藏时放入内存中,重新调用的时候再从内存中拿出来,通过 `v-once`指令,可以有效提高一些静态内容的展示效率。 #### Vue中的CSS动画原理 为Vue元素添加动画时,需要用``标签包住元素,这样才能为Vue元素添加动画效果,当你不为``标签指定一个`name`时,动画样式的前缀默认为`v-`,还可以在``使用`-class`为`enter`和`leave`动画指定一个CSS样式名字,这样Vue就会使用你指定的样式名字。(这个时候就不在需要`name`) Vue动画从开始到结束会有3个过程即从开始到结束和中间,进入过程:Vue会为这三个不同的过程中添加不同的CSS样式:`enter`、`enter-active`、`enter-to`。 与之相似,退出过程也会有三个CSS样式:`leave`、`leave-active`、`leave-to`。 ##### 为什么使用enter作为动画的入场开始: 使用`enter`作为入场开始是因为动画在默认情况下`opacity`为1,这时需要在第一帧是将其写为0,在之后的进行中中过程中`enter`会被移除,这时`opacity`为0。 ##### 为什么使用leave-to作为动画的出场开始: 使用`leave-to`作为出场开始是因为动画第一帧`opacity`需要为1,从第二帧开始`leave`被移除,这时`opacity`的值还是1,需要将其改为0,动画才会被正常触发。 #### 在Vue中使用animate.css库 库的动画是CSS3标准的动画。由于Vue可以更改CSS样式的名字,所以我们可以使用在实现复杂的动画时可以使用使用一些CSS库如animate.css,用`-class`为动画指定名字为CSS库的样式名字,实现CSS库的绑定。 #### 在Vue中同时使用过渡和动画 ##### 元素第一次显示的动画效果: 当需要元素第一次显示时也有动画效果,需要在``标签中写入两个属性:`appear`、`appear-active-class`,第一个表示第一次显示元素时也有动画效果,第二个表示动画效果的CSS规则,它的值就是CSS动画规则名。 ##### 同时使用CSS库和过渡动画: 要实现这种效果,需要为在``标签中为元素绑定两个CSS规则,分别为CSS库动画和过渡动画——`enter`和`leave` ##### CSS库和过渡动画执行时间不一致: 在使用CSS库的时候,而它往往都是固定的,而自定义的过渡效果可能和它不一样,这是可以在``标签中写一个新的属性type,它的值决定了最终动画时长以谁为准(`animation` 或 `transition`) >**来自官方的解释**:Vue 为了知道过渡的完成,必须设置相应的事件监听器。它可以是 `transitionend` 或 `animationend`,这取决于给元素应用的 CSS 规则。如果你使用其中任何一种,Vue 能自动识别类型并设置监听。 >但是,在一些场景中,你需要给同一个元素同时设置两种过渡动效,比如 `animation` 很快的被触发并完成了,而 `transition` 效果还没结束。在这种情况中,你就需要使用 `type attribute` 并设置 `animation` 或 `transition` 来明确声明你需要 Vue 监听的类型。 ##### 显性的过渡持续时间: 在大多数情况下,Vue可以自动得出动画所需要的执行时长,当然也可以用`duration`属性定制执行时长(这个属性需要用v-bind绑定,并且以毫秒表示)。`duration`属性的值还可以是多个,用{}符号包裹,这个情况下可以分别为`enter`和`leave`动画定制执行时长。 #### Vue中的JS动画 在Vue动画的开始和结束,有6个JS钩子,它们分别是: `before-enter`:入场动画之前 `enter`:入场动画执行中 `after-enter`:入场动画之后 `before-leave`:出场动画之前 `leave`:出场动画执行中 `after-leave`:出场动画之后 #### Vue中多个元素或组件的过渡 Vue在渲染网页的时候会尽量复用页面上已有的`DOM`,在使用Vue的动画效果时可能会产生一些问题,这时候也需要为元素指定`Key`值,保证动画的正常执行。 ``标签中有一个属性叫:`mode`,它有两个值:`in-out`和`out-in`,`mode`的值为`in-out`时,动画会先显示再隐藏,而`out-in`则与之相反,不使用`mode`属性时,动画就会同时执行。多个组件的过渡动画可以使用动态组件来实现。 #### Vue的列表过渡 与单个元素使用动画效果不同,列表渲染相当于渲染多个元素的,这是``标签不支持的,这时候就需要使用``标签,这个标签相当于为每一个渲染的元素添加上一个``标签。 #### Vue中的动画封装 在很多时候一个相同的动画会用上很多次,尽管他们的元素各不相同,这样一来,每为一个元素设定这个动画都需要重复编写``,这是很不方便的,为了解决这个问题,我们可以使用Vue组件来对重复使用的动画进行封装。除此之外还可以将CSS规则进行封装,用Vue动画的6个JS钩子将它改写为JS动画写在组件的`methods`中。 #### 拓展 或许我可以用Vue的模板功能来生成一个带有Vue实例接管的模板,例如: `template: "Hello Wrold"` 在Vue框架的使用中,你可以使用一个叫`