前言:这一篇旨在教大家快速入门Vue2,每个知识点用案例解释

不过学习vue2之前,建议学好JavaScript的基础知识:

前端程序员需要了解的JavaScript_成为前端大牛的博客-CSDN博客

目录

一:声明式渲染

二:条件和渲染

条件:

渲染:

三:处理用户操作

1:操作

2:文本框双向绑定

四:组件化

组件的样式:

为啥data必须是一个函数:

组件传值prop:

单向数据流:

props验证:type,required,default(如果是数组对象类型,需要是工厂函数返回数组对象的格式),自定义validator验证函数,返回true

优先级:

组件的监听事件$emit:

.sync修饰符:

组件的v-model:

组件的插槽:

插槽的分类:

解构插槽Prop:

动态插槽名:

注意:

动态组件:这个是重点

动态组件:keep-alive

动态组价的过渡效果:

组件的其他交互传值情况:

1:访问元素

五:Vue实例

1:数据与方法

2:实例的生命周期

拥有八个生命周期

父子组件生命周期顺序:

六:模板语法 template

1:插值表达式:v-text,v-html

2:指令:

七:计算属性

计算属性的解释

计算属性与普通函数的区别:

修改计算属性的值,通过set访问器

八:监听属性

使用场景:

深度监听对象,立即执行:

注意:

九:style和class绑定

十:组件动画和过渡

如何使用:

使用场景:

过渡效果:

动画效果结合动画库:

如何vue引入animate.css

利用js函数钩子实现过渡或者动画:

初始过渡:

多个元素的过渡:

多个元素的区分:

列表过渡:

状态过渡:

可复用性:

混入mixin:

高级使用:

自定义指令:

指令的动态参数

自定义指令的目的:

自定义指令简写:

渲染函数render 结合jsx:

什么时候使用render:

对于vnode的理解:

render属性方法:

createElement回调函数接受三个参数

render理解:其实很简单

render结合jsx:

函数式组件 functional:

官方API:

规模化:

1:路由:

2:全局状态管理

深入响应式原理:


一:声明式渲染

vue是单页面应用,一个vue应用直接挂载到一个dom元素上,其余的都创建在vue的实例里面

文本插值{{}},里面可以做字符串拼接,js逻辑运算(三元目算符等等)

 <h1>{{ data + 1 }}</h1><h1>{{ data + '1' }}</h1><h1>{{ `${data}1` }}</h1><h1>{{ Math.round(data) }}</h1>

除了文本插值,我们还可以像这样来绑定元素 attribute:

<div id="app-2"><span v-bind:title="message">鼠标悬停几秒钟查看此处动态绑定的提示信息!</span>
</div>var app2 = new Vue({el: '#app-2',data: {message: '页面加载于 ' + new Date().toLocaleString()}
})

二:条件和渲染

条件:

  1. v-if 和 v-else-if 和 v-else。v-show是频繁的切换页面使用
  2. v-if可以绑定在复杂的div上,可以结合Vue过渡效果完美体现
  3. v-if  可以结合 key  标识唯一的attribute ,这样在不同模板中复用的元素就会独立起来,复用的元素也会重新渲染一遍
  4. 当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级。请查阅列表渲染指南以获取详细信息。
  5. v-if可以使用在模板语法template上
    <h2 v-if="demo > 1">12</h2><h2 v-else-if="demo < 3">12</h2><h2 v-else>12</h2>demo: 4,只显示第一个<div v-if="type === 'A'">A
</div>
<div v-else-if="type === 'B'">B
</div>
<div v-else-if="type === 'C'">C
</div>
<div v-else>Not A/B/C
</div>

过渡显示例子:

渲染:

  1. v-for,可以渲染数组和对象,注意绑定唯一key值
  2. v-for 也可以接受整数。<span v-for="n in 10">{{ n }} </span>
  3. v-for可以使用在template上
 <div v-for="(item, index) in arrlist" :key="index">{{ `${item}-${index}` }}</div><div v-for="(value, key, index) in objlist" :key="index">{{ `${value}-${key}-${index}` }}</div>

复杂demo:v-if和v-for结合使用

    <template v-for="(i, index) in blist"><div :key="index" v-if="i.status">{{ i.status }}</div></template>blist: [{ status: true }, { status: false }, { status: true }],

三:处理用户操作

1:操作

  1. 为了让用户和你的应用进行交互,我们可以用 v-on 指令添加一个事件监听器,通过它调用在 Vue 实例中定义的方法:简写@
  2. 注意:我们更新了应用的状态,但没有触碰 DOM——所有的 DOM 操作都由 Vue 来处理,你编写的代码只需要关注逻辑层面即可。
  3. 有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event 把它传入方法
  4. 六个事件修饰符
  5. 按键修饰符
  6. .stop - 调用 event.stopPropagation()。
    .prevent - 调用 event.preventDefault()。
    .capture - 添加事件侦听器时使用 capture 模式。
    .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
    .{keyCode | keyAlias} - 只当事件是从特定键触发时才触发回调。
    .native - 监听组件根元素的原生事件。
    .once - 只触发一次回调。
    .left - (2.2.0) 只当点击鼠标左键时触发。
    .right - (2.2.0) 只当点击鼠标右键时触发。
    .middle - (2.2.0) 只当点击鼠标中键时触发。
    .passive - (2.3.0) 以 { passive: true } 模式添加侦听器

2:文本框双向绑定

  1. Vue 还提供了 v-model 指令,它能轻松实现表单输入和应用状态之间的双向绑定。
  2. v-model适用于表单元素上,它负责监听用户的输入事件以更新数据,并对一些极端场景进行一些特殊处理。
  3. 三个 v-model修饰符

v-model 在内部为不同的输入元素使用不同的 property 并抛出不同的事件:

  • text 和 textarea 元素使用 value property 和 input 事件;
  • checkbox 和 radio 使用 checked property 和 change 事件;
  • select 字段将 value 作为 prop 并将 change 作为事件。

联合demo:

    <button @click="todo">点我</button><input type="text" v-model="text" />todo(e) {this.text = e.target.innerHTML;},

四:组件化

  1. 在 Vue 里,一个组件本质上是一个拥有预定义选项的一个 Vue 实例
  2. 父组件可以将父级作用域的数据通过prop传给子组件
  3. 在我们编程中,尽可能可以把设计变成组件化,你可以选择传参给子组件,他只接受你的值然后把要做的事抛给父亲。
  4. 也可以单独在子组件内做请求的事情,你可以看作他是一个页面的一块,类似于elementui的每个组件,可以自己设计
  5. 每调用一次组件,就会有一个它的新实例被创建。

其他组件理解:

组件的样式:

  1. 对于父子组件来说,在父组件定义的样式控制着父组件里面的元素,包括子组件,所以对于布局样式,可以写在子组件标签上面,你也可以用一层div包裹着子组件,在div上面写布局样式。如果说样式写在了子组件标签上,则相当于把样式也直接给到了子组件实例上,直接干预子组件的css,他的层级比子组件自己定义的样式高。
  2. 子组件的样式控制子组件里面的元素。
  3. 所以对于组件样式的理解,就是哪个组件内的样式控制哪个组件的元素。
  4. 上面的图片例子 也可以直接说明我们使用类似于elementui框架的input组件一样的,直接在input组件上写class,能覆盖到他的样式
  5. 如果说样式写在包裹子组件的div上,子组件此时是div里面的内容,是没有宽高的。设置子组件内部样式时记得设置宽高,比如width: 100%;   height: 100%;
  6. 我们常用的当然是:用div包裹子组件,在父组件清晰的css定义布局,然后子组件设置宽高,控制子组件里面的元素。
  7. 你把子组件标签当成一个div来理解,就清晰多了。

为啥data必须是一个函数:

如果不是函数的返回值,那这个data对象可能在多次调用该组件时,生成很多新实例时,该对象会共享引用,不会出现独立性的表现。会影响到该组件被别人调用时,状态的改变。

所以规定一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:

组件传值prop:

一个 prop 被注册之后,你就可以像这样把数据作为一个自定义 attribute 传递进来:在组件实例里新增proprety。

 props: {date: {type: String,default: '默认值',},},

单向数据流:

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外变更父级组件的状态,从而导致你的应用的数据流向难以理解。

如果你想修改props,我们有三种方法:

如果你是确定要改props值,而不是做其他事情,就直接使用.sync语法糖

1:在子组件data里定义一个property 来接受props,后续使用data里面的属性来操作,作为本地使用

这里有个注意的事情:就是你修改了本地的data,如果这个prop是个对象等引用类型,因为你data=prop的话,就会涉及传地址问题,修改了data的话也修改了prop传过来的父组件的值,可能会影响到父组件的状态

props: ['initialCounter'],
data: function () {return {counter: this.initialCounter}
}

2:如果你是想对这个props进行一个复杂计算,我们也可以在子组件里使用computed来定义 

props: ['size'],
computed: {normalizedSize: function () {return this.size.trim().toLowerCase()}
}

3:.sync修饰符

下面自定义事件章节 有详细介绍

props验证:type,required,default(如果是数组对象类型,需要是工厂函数返回数组对象的格式),自定义validator验证函数,返回true

Vue.component('my-component', {props: {// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)propA: Number,// 多个可能的类型propB: [String, Number],// 必填的字符串propC: {type: String,required: true},// 带有默认值的数字propD: {type: Number,default: 100},// 带有默认值的对象propE: {type: Object,// 对象或数组默认值必须从一个工厂函数获取default: function () {return { message: 'hello' }}},// 自定义验证函数propF: {validator: function (value) {// 这个值必须匹配下列字符串中的一个return ['success', 'warning', 'danger'].indexOf(value) !== -1}}}
})

优先级:

props的优先级最高

props > methods > data > computed > watch

组件的监听事件$emit:

可以将子组件发生的事件传给父组件。

this.$emit('todo', '是');

.sync修饰符:

就是一个语法糖,省略了在子组件标签上的自定义方法,优雅不是粗鲁的实现props双向修改

有两种情况使用:

1:字符串或者数字等标准数据结构

在子组件标签上   :demo.sync="demo"   

在子组件里面的methods属性方法里写

 methods: {demo() {this.$emit('update:demo', 2);},},

区别就是加上update :加上props名

此时父组件的data值就改变了

2:给复杂的对象的引用类型,加上.sync

在子组件标签上写     v-bind.sync="edit"    这个edit是一个对象  edit:{ name:1 }

在子组件里面的props里面写 edit这个对象的属性,你要改哪个就写哪个edit的属性

 props: {name: Number,//edit对象的属性},

在子组件里面的methods属性方法里写

editdemo() {this.$emit('update:name', 2);},

此时父组件的data值就改变了

总结sync:简单地说就是props的那个子组件标签上的atrra加上.sync,然后子组件里的emit里面加上update,子组件标签上少写一个自定义事件。就形成了语法糖。

组件的v-model:

v-model的简单原理是:表单的input等表单事件改变$event.target.value(demo),将这个值给组件实例对象,对象属性监听触发set方法,把改的值传给dom节点的attra

<input v-model="searchText">

等价于:

<inputv-bind:value="searchText"v-on:input="searchText = $event.target.value"
>

所以在组件上的v-model可以使用该原理。

组件的插槽:

有时候我们需要在子组件的标签里面放点元素,如果直接放就会报错,所以在子组件里面先定义好插槽,就可以再放了,插槽内可以包含任何模板代码,包括 HTML或者组件。这就是插槽的意义。

插槽的分类:

1:普通插槽:

定义slot标签,里面可以放默认内容

<slot > 默认内容 </slot><slot  :v="v">默认作用域插槽</slot>当只有默认插槽时,可以吧v-slot写在子组件标签上,下面是简写的普通作用域插槽
<child v-slot="slotProp">{{slotProp.v}}<child/>

2:具名插槽:

用name做标识

<slot name="header"></slot>在父组件里的子组件标签内 写v-slot<template v-slot:header><h1>Here might be a page title</h1></template>或者 <div slot="header">123</div>     这种slot已经被废弃了,但是还是可以使用

注意: v-slot只能使用在 template 模板标签上,如果当前子组件里面只有一个默认插槽,让我们可以把v-slot写在子组件标签上,v-slot有简写形式 : #

3:作用域插槽:

有时让插槽内容能够访问子组件中才有的数据是很有用的,我们可以这样实现

在子组件slot标签上 绑定一个attribute 给子组件的数据,这个user是子组件data里的属性
直接认为是插槽的prop,传给外面用的
<span><slot v-bind:user="user">{{ user.lastName }}</slot>
</span>这个绑定在 <slot> 元素上的 attribute 被称为插槽 prop在父组件中的子组件标签上加上 v-slot绑定slot标签的名字 = 一个字符串,然后就可以拿着这个字符串去调用
传过来的子组件的数据,这个字符串随便命名
这样就可以拿到子组件作用域的数据了
<current-user><template v-slot:default="slotProps">{{ slotProps.user.firstName }}</template>
</current-user>

解构插槽Prop:

因为你在slot标签上绑定的子组件的数据的那个插槽props,在父组件内使用,他是可以解构的

因为插槽props是一个对象,所以就可以直接解构他,也可以用到解构的所有知识,包括默认值

   这个里面的  v-slot:demo="pro"   pro就是插槽props,我们可以解构他,他是一个对象
v-slot:demo="pro"  ==  v-slot:demo="{ v }"   我们就可以直接用v<hello-world :date="date" v-bind.sync="edit" @todo="chang"><template v-slot:demo="pro"><span>{{ pro.v }}</span><slotvue :slotprop="pro.v" :isdaka="isdaka"></slotvue></template></hello-world>解构之后<hello-world :date="date" v-bind.sync="edit" @todo="chang"><template v-slot:demo="{ v }"><span>{{ v }}</span><slotvue :slotprop="v" :isdaka="isdaka"></slotvue></template></hello-world>

解构插槽Props的默认参数: 就是es6解构对象属性的默认参数

v-slot="{ user = { firstName: 'Guest' } }"

动态插槽名:

v-slot:绑定的是具名插槽的名字,现在这个名字可以用变量代替,形成动态的绑定到子组件内的具名插槽。

<base-layout><template v-slot:[dynamicSlotName]>...</template>
</base-layout>

注意:

在子组件标签内的内容是属于父组件作用域的。一条规则,当前组件内的东西都属于当前组件作用域 。官网这么介绍的:父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

动态组件:这个是重点

可以通过 Vue 的 <component> 元素加一个特殊的 is attribute 来实现:替换不同组件的v-if判断

<!-- 组件会在 `currentTabComponent` 改变时改变 -->
<component v-bind:is="currentTabComponent"></component>

在上述示例中,currentTabComponent 可以包括

  • 已注册组件的名字,  就是你定义的组件名字,别忘记在父组件里引入
  • 一个组件的选项对象

动态组件我们就不用写那么多代码,直接绑定is控制要显示的组件名(需要在data里定义这个变量名comName,给个默认值第一个要展示的组件名),动态组件存在两种情况优化,缓存和动画

  <component :is="comName"></component>data() {return {comName: 'Apple',//第一次展示的是叫apple的组件名};},

动态组件:keep-alive

希望那些标签的组件实例能够被在它们第一次被创建的时候缓存下来,为了解决这个问题,我们可以用一个 <keep-alive> 元素将其动态组件包裹起来。

<!-- 失活的组件将会被缓存!-->
<keep-alive><component v-bind:is="currentTabComponent"></component>
</keep-alive>

意思就是我们切换组件的时候,能把切换之前的这个组件状态缓存起来,我们再切换回来的时候任然保持之前的状态。

一般我们根据route的信息拿到路由对象里面的meta属性来控制哪些组件是否需要缓存。

 缓存组件和过渡组件的结合使用:

<!-- 和 `<transition>` 一起使用 -->
<transition><keep-alive><component :is="view"></component></keep-alive>
</transition>

动态组价的过渡效果:

在过渡那章会介绍

组件的其他交互传值情况:

1:访问元素

  1. 访问根元素:$root
  2. 访问父组件实例:$parent  ,子实例可以用 this.$parent 访问父实例
  3. 访问子组件实例:$children
  4. 访问子组件实例或者子元素:$refs  一个对象
  5. 依赖和注入 provide 和 inject  ,不是响应式的,但是对于传入的可监听对象,对象的属性还是响应式

refs:是一个对象,可以访问包含ref该attr的标签DOM元素和组件实例

$refs 只会在组件渲染完成之后生效,并且它们不是响应式的。这仅作为一个用于直接操作子组件的“逃生舱”——你应该避免在模板或计算属性中访问 $refs

不是响应式的。尽量避免使用

provide和inject:

你可以把依赖注入看作一部分“大范围有效的 prop”,除了:

  • 祖先组件不需要知道哪些后代组件使用它提供的 property
  • 后代组件不需要知道被注入的 property 来自哪里
 // 父组件定义的属性方法,和methods同级provide() {return {isdaka: this.isdaka,};},其他后代组件接收inject: ['isdaka'],

缺点:同时所提供的 property 是非响应式的,会造成大量耦合,项目里基本使用vuex

难点是对于全局公共组件的设计,components


五:Vue实例

每一个vue组件都是一个vue实例对象,并且接受相同的选项对象。

export default {name:'component', // 组件名components:{}, // 子组件directives:{}, // 自定义指令filters:{}, // 过滤器mixins:{}, // 混入model:{}, // 定义v-modelprops:{}, // 父组件传递的propdata() {return {} // 本地状态},computed:{}, // 计算属性watch:{}, // 监听器created(){}, // 创建时的钩子mounted() {}, // 挂载时的钩子beforeDestroy(){}, // 销毁前的钩子methods: {}, // 方法render(h) {}, // 渲染函数
}

vm是组件的实例对象,一般组件的this指向实例对象vm

var data = { a: 1 }// 直接创建一个实例
var vm = new Vue({data: data
})
vm.a // => 1
vm.$data === data // => true

1:数据与方法

数据是双向绑定的,使用Object.freeze()可以冻结data对象属性的增删改,从而终止响应式变化。对于Vue的实例对象 中的属性可以前缀 $,以便与用户定义的 property 区分开来,例如watch,computed那些实例属性

2:实例的生命周期

每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

生命周期的this指向调用它的 Vue 实例,

拥有八个生命周期

 beforeCreate() {console.log('在实例初始化之后,进行数据侦听和事件/侦听器的配置之前同步调用。');},created() {console.log('在实例创建完成后,回调函数配置完成,未挂载dom');},beforeMount() {console.log('在挂载开始之前被调用:相关的 render 函数首次被调用。');},mounted() {console.log('实例挂载dom节点,不会保证所有的子组件也都被挂载完成,可以在该周期内使用 nextTick控制整个视图渲染完毕后执行操作');},beforeUpdate() {console.log('这里适合在现有 DOM 将要被更新之前访问它,比如移除手动添加的事件监听器。');},updated() {console.log('更新完成');},beforeDestroy() {console.log('实例销毁之前调用。在这一步,实例仍然完全可用。');},destroyed() {console.log('已销户');},实例完成,回调函数未成功配置实例完成,各种回调函数配置已完成挂载dom之前,render函数调用已挂载实例,但不能保证所有子组件全部更新更新之前更新完成销毁之前。能使用实例已销户销毁之前已销户

详细版如下:

父子组件生命周期顺序:

父组件创建页面,然后子组件创建,子组件渲染完成,再父组件渲染

创建实例从外到内,渲染从内到外

父beforeCreate —> 父created —> 父beforeMount —> 子beforeCreate —> 子created —> 子beforeMount —> 子mounted —> 父mounted

简单的说就是父组件挂载dom之前走子组件生命周期 ,子组件渲染完,再回到父组件挂载dom元素完成


六:模板语法 template

Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML,所以能被遵循规范的浏览器和 HTML 解析器解析。

在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。

如果你熟悉虚拟 DOM 并且偏爱 JavaScript 的原始力量,你也可以不用模板,直接写渲染 (render) 函数,使用可选的 JSX 语法。

意思是Vue的模板语法会经过vue底层,虚拟dom渲染函数去渲染生成html

1:插值表达式:v-text,v-html

可以使用单个的js表达式,或者绑定元素的 HTML attribute

2:指令:

vue指令篇(v-if,v-for,v-bind,v-model,v-on,计算属性,监听器,过滤器)_成为前端大牛的博客-CSDN博客

新增动态参数:

从 2.6.0 开始,可以用方括号括起来的 JavaScript 表达式作为一个指令的参数:

<!--
注意,参数表达式的写法存在一些约束,如之后的“对动态参数表达式的约束”章节所述。
-->
<a v-bind:[attributeName]="url"> ... </a>

这里的 attributeName 会被作为一个 JavaScript 表达式进行动态求值,求得的值将会作为最终的参数来使用。例如,如果你的 Vue 实例有一个 data property attributeName,其值为 "href",那么这个绑定将等价于 v-bind:href

同样地,你可以使用动态参数为一个动态的事件名绑定处理函数:

<a v-on:[eventName]="doSomething"> ... </a>

在这个示例中,当 eventName 的值为 "focus" 时,v-on:[eventName] 将等价于 v-on:focus

指令修饰符 ,上文有讲


七:计算属性

计算属性的解释

对于任何复杂逻辑,你都应当使用计算属性

对于 computed这个对象来说,写在里面的计算属性 即声明的属性方法,Vue把它这个function  作为了这个定义的计算属性的getter函数

 computed: {// 计算属性的 getterreversedMessage: function () {// `this` 指向 vm 实例return this.message.split('').reverse().join('')}}

这里我们声明了一个计算属性 reversedMessage。我们提供的函数将用作 property vm.reversedMessage 的 getter 函数:

计算属性与普通函数的区别:

计算属性拥有缓存,基于响应式依赖,只有当依赖值发生改变时,才会从新计算。

对于方法来说,只要重新渲染,调用方法总会再次执行函数

我们为什么需要缓存?假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。

简而言之,对于你需要有缓存的复杂的计算 就用计算属性,减少前端性能、

计算属性也可以返回一个函数,在页面上声明是传参,因为计算属性是一个getter函数

 computed: {jisuan() {return function (a) {return this.arrlist.map((i) => i + a);};},},<div>{{ jisuan(2) }}</div>

要理解定义的计算属性,他只是个属性而已 ,不是属性方法,他的返回值是getter函数计算的结果

修改计算属性的值,通过set访问器

计算属性默认只有getter,所以简写成属性方法的样子,如何设置setter呢

  computed: {jisuan(a) {return this.arrlist.map((i) => i + a);},此时把setDemo计算属性的值写成对象形式setDemo: {   get() {return this.objlist.name;},set(v) {console.log('1111', v);this.objlist.name = v;},},},通过在别的地方修改 this.setDemo  = 3  可以修改掉get()返回的值,从而改变setDemo的值

计算属性常常配合Vuex使用,这样就可以从状态管理那里读取过的数据缓存在当前组件实例中使用。


八:监听属性

我们常常使用计算属性就能得到变化的值,但有时候我们也想自定义监听数据的变化。

使用场景:

当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

比如监听data里面表格数据的变化,只要变化了重新请求异步函数拉取最新值,或者监听表单输入时,执行异步查询

 watch: {setDemo(New, old) {console.log(New, old);alert('变化了');setTimeout(() => {this.setDemo = 1;}, 2000);},},

深度监听对象,立即执行:

比如我们想深度监听对象的属性变化,或者我们想立即实行监听方法,可以这样操作

watch: {将属性的值写成对象形式setDemo: {deep: true, //深度监听immediate: true, //立即执行回调,就是说改变通常是第二次触发,加了这个属性意味着第一次就执行handler(n, o) {console.log(n, o);  //本身和 undefined},},},

注意:

watch能监听复杂的数组结构的变化。但是拿不到新旧值,例如

blist: [{ status: true }, { status: false }, { status: true }],  数组对象形式,永远只有一个新值。

但是能检测到普通数组的变化。拿到新旧值

因为deep只对复杂的对象起作用,无法对复杂的数组起作用

当data里对象的属性值发生改变时,watch监听不到,他只会监听对象属性的增删。对改查没用


九:style和class绑定

这个我用的最多的就是根据数据的值结合  三元运算符  去显示哪个类的样式。这个点不做多的解释,他们一般绑定data或者computed里面的变量.

十:组件动画和过渡

如何使用:

Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。包括以下工具:

  • 在 CSS 过渡和动画中自动应用 class  就是写css
  • 可以配合使用第三方 CSS 动画库,如 Animate.css   把css库引入到transition 组件的attra来
  • 在过渡钩子函数中使用 JavaScript 直接操作 DOM   transition 标签上的js钩子函数
  • 可以配合使用第三方 JavaScript 动画库,如 Velocity.js   库用到钩子函数上

使用场景:

Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡

  • 条件渲染 (使用 v-if)
  • 条件展示 (使用 v-show)
  • 动态组件     用的多
  • 组件根节点    App.vue

过渡效果:

transition组件提供 六个css类名来控制过渡

//刚开始进入
.fade-enter {opacity: 0;
}
//进入中
.fade-enter-active {transition: all 0.5s;
}
//进入结束
.fade-enter-to {opacity: 1;
}
//离开
.fade-leave {opacity: 1;
}
//离开过程
.fade-leave-active {transition: all 0.5s;
}
//离开结束
.fade-leave-to {opacity: 0;
}

我们可以根据经验去判断,进入和离开状态一致进入结束和离开的状态一致(可以只写一个),在active过程中写过渡css

简写形式:

简写形式.fade-enter,
.fade-leave-to {opacity: 0;
}在动态组件身上时,可以只写一种状态过渡 或者可以使用过度模式mode解决
.fade-enter-active {transition: all 0.5s;
}
.fade-leave {opacity: 1;
}
  1. 经过验证在动态组件身上,只写一个active的过渡css比较好
  2. active类上面可以写过渡transition  也可以写· animation: ;
  3. 如果运用自己写动画,只需要设置active类的css

动画效果结合动画库:

结合 Animate.css 使用transition  组件,可以自定义类名,

把进入的这些类名改为animatecss的类名<transitionname="custom-classes-transition"enter-active-class="animated tada"leave-active-class="animated bounceOutRight"><p v-if="show">hello</p></transition>

如何vue引入animate.css

1:npm install animate.css@3.5.1 --save

2:在main.js里面   import animated from 'animate.css'

3:在标签class上写的时候加上 animated

利用js函数钩子实现过渡或者动画:

省略。。。

初始过渡:

appear属性

      <transitionname="fade"enter-active-class="animated fadeInLeftBig"appear="appear"                                //第一次进入appear-active-class="animated fadeInLeftBig"   //第一次进入的动画><component :is="comName"></component></transition>

多个元素的过渡:

多个元素的区分:

意义:可以用在项目上的tabs选项卡的切换 以及 表格 功能区的编辑保存按钮的实现

如果多个元素是不同的标签:

老老实实写v-if,v-else,这种情况我试了一下 无法触及到过渡动画,如果是单标签就可以

       控制is的真假,但是过渡不出现  <transition enter-active-class="animated bounceIn"><div v-if="is">{{ text }}</div><div v-else><input type="text" v-model="text" /></div></transition>

如果多个元素是相同的标签

当有相同标签名的元素切换时,为了省略v-if v-else,需要通过 key attribute 设置唯一的值来标记以让 Vue 区分它们,否则 Vue 为了效率只会替换相同标签内部的内容。即使在技术上没有必要,给在 <transition> 组件中的多个元素设置 key 是一个更好的实践。

加上key绑定两个判断,使用三元运算符
<transition><button v-bind:key="isEditing">{{ isEditing ? 'Save' : 'Edit' }}</button>
</transition>超过两个判断,则使用计算属性
<transition><button v-bind:key="docState">{{ buttonMessage }}</button>
</transition>computed: {buttonMessage: function () {switch (this.docState) {case 'saved': return 'Edit'case 'edited': return 'Save'case 'editing': return 'Cancel'}}
}

如果多个元素是组件 

如果你是多个组件,我的建议是写成动态组件,因为写那么多v-if没必要,如果是单个标签要判断不同条件显示不同效果(例子是 表格上的编辑保存取消按钮 ),建议使用计算属性

    <div class="show"><transition><component :is="comName"></component>  //使用动态组件,控制:is的变量值</transition></div>

在动态组件中使用两个过渡active状态会不好看,这个时候引入了 mode 过度模式

同时生效的进入和离开的过渡不能满足所有要求,所以 Vue 提供了过渡模式

  • in-out:新元素先进行过渡,完成之后当前元素过渡离开。

  • out-in:当前元素先进行过渡,完成之后新元素过渡进入。

      <transitionname="fade" mode="out-in"  //过渡模式  引入了这个后可以写两个active状态了enter-active-class="animated fadeInLeftBig"leave-active-class="animated wobble"appear="appear"appear-active-class="animated fadeInLeftBig"><component :is="comName"></component></transition>

列表过渡:

上面的过渡只是针对单个的过渡,对于列表的过渡 我们使用 group

这里平时用的少,就省略了。。。

状态过渡:

我们过度的那个name可以v-bind绑定一个变量的,然后结合过渡钩子函数,切换这个变量实现状态的过渡。


可复用性:

混入mixin:

提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

就是说你觉得哪些可以复用,你就少写些代码

高级使用:

自定义指令:

你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {// 当被绑定的元素插入到 DOM 中时……inserted: function (el) {// 聚焦元素el.focus()}
})单个vue组件directives: {focus: {// 指令的定义inserted: function (el) {el.focus()}}
}

一个自定义的指令对象里面接受5个钩子函数,这五个属性方法代表五个周期,接受四个参数

 <p v-yuyi="date"></p>directives: {yuyi: {// 只调用一次,指令第一次绑定到元素时调用。一次性的初始化设置bind(el, binding, vnode) {console.log('dom节点', el);console.log('指令后绑定的值,是一个对象,包括指令名字,指令值,指令参数等', binding);console.log('当前组件虚拟节点', vnode);},// 被绑定元素插入父节点时调用inserted() {},// 所在组件的 VNode 更新时调用update(oldVnode) {},// 指令所在组件的 VNode 及其子 VNode 全部更新后调用componentUpdated() {},//只调用一次,解绑unbind() {},},},data() {return {date: '2022-05-13',};},

指令的动态参数

这个v-yuyi可以绑定参数比如 v-yuyi:title ,这个title就是参数,这个参数可以动态传值(v-mydirective:[argument]="value" 中,argument 参数可以根据组件实例数据进行更新!)。

blinding这个对象里argument这个属性代表参数名,modifiers这个代表参数的修饰符对象 ,比如v-yuyi:title.todo ,这个todo就是修饰符对象的一个属性。

自定义指令的值可以是一个对象字面量,比如v-yuyi=”{name:1}“

自定义指令的目的:

我们可以在五个属性方法里直接操作dom元素 也可以拿到binding对象里的value值(指令绑定的值),然后进行dom操作

     bind(el, binding, vnode) {console.log('dom节点', el);el.innerHTML = binding.value;},

自定义指令简写:

在很多时候,你可能想在 bind 和 update 时触发相同行为,而不关心其它的钩子。比如这样写:

 directives: {// 在 bind 和 update 时触发相同行为,而不关心其它的钩子,直接写成指令的属性方法形似yuyi(el, binding, vnode) {console.log(el, binding, vnode);},},

渲染函数render 结合jsx:

Vue 推荐在绝大多数情况下使用模板来创建你的 HTML。然而在一些场景中,你真的需要 JavaScript 的完全编程的能力。这时你可以用渲染函数,它比模板更接近编译器。

什么时候使用render:

在我的理解里什么时候用模板语法什么时候用render函数:

  1. 如果你想更多的操作虚拟doms树,去操作html标签,你可以选择render
  2. 因为平时我们写html不是写的死的吗,很难根据动态的改变,而render可以去渲染虚拟dom节点树。
  3. 这个用法比较的灵活。

对于vnode的理解:

  1. html的渲染都是通过节点树来一层层的往下渲染的。它会建立一个“DOM 节点”树来保持追踪所有内容,如同你会画一张家谱树来追踪家庭成员的发展一样。
  2. vnode是vue通过建立的虚拟节点,“虚拟 DOM”是我们对由 Vue 组件树建立起来的整个 VNode 树的称呼。他是针对性的去选择建立真实的dom树。

render属性方法:

render是一个vue实例的property属性方法,他接受参数为一个回调函数createElement,然后把这个函数返回出去

createElement回调函数接受三个参数

1:渲染名(// {String | Object | Function}  // 一个 HTML 标签名、组件选项对象,或者 // resolve 了上述任何一种的一个 async 函数。必填项。)

2:// {Object}  // 一个在渲染名上的attribute 对应的数据对象。可选。就是你平时在template里面写该标签能使用的标签属性attribute,比如id啥的,如果是组件就有prop等

3:// {String | Array}  // 子级虚拟节点 (VNodes)由 `createElement()` 构建而成, // 也可以使用字符串来生成“文本虚拟节点”。可选。

  data() {return {name: 'yy',};}, // render是一个vue实例的property属性方法,他接受参数为一个回调函数createElement,然后把这个函数返回出去render(createElement) {return createElement('h1', {}, this.name);},

界面上就出现了h1标签包裹的yy,把yy渲染出来了

render理解:其实很简单

createElement的三个参数,

  1. 第一个参数就是你的标签名或者组件名,
  2. 第二个参数就是你这个标签上的属性,比如普通的html标签上面会加id或者class,这些个属性就写在第二个参数对象里面,对于组件的话当然是prop传参那些,vue的指令得要用js的逻辑实现。
  3. 第三个参数是一个数组,用来写层级的,数组的每一项为一个评级,数组项里写createElement又会创造一层虚拟dom树来
 render(createElement) {return createElement('h1',{class: {h1: true,},},[this.name,createElement(RenderChild, {props: {num: this.child,},}),]);},

render结合jsx:

render函数结合jsx,让我们回到更接近于模板的语法上。此时的createElement可以写成h,而且return 返回可以省略h参数

 render(h) {return (<div><p>这个是打算用render写的子组件{this.num}</p><RenJsx sex={this.sex}></RenJsx></div>);},

函数式组件 functional:

使组件无状态 (没有 data) 和无实例 (没有 this 上下文)。他们用一个简单的 render 函数返回虚拟节点使它们渲染的代价更小。

不管理自己的状态,也不监听传过来的状态,,无自己的状态,只做props的传递,展示页面。减少开销可以使用函数时组件在这样的场景下,我们可以将组件标记为 functional,这意味它无状态 (没有响应式数据),也没有实例 (没有 this 上下文)。一个函数式组件就像这样:

使用模板标签的 函数式组件

<template functional>
</template>

render 写函数时组件,将组件所有的数据都放到了context参数身上

Vue.component('my-functional-button', {functional: true,render: function (createElement, context) {// 完全透传任何 attribute、事件监听器、子节点等。return createElement('button', context.data, context.children)}
})

官方API:

前端程序员怎么样快速了解Vue2的高级知识,这一篇文章会给你答案_成为前端大牛的博客-CSDN博客

规模化:

1:路由:

2:全局状态管理

深入响应式原理:

前端程序员需要了解的Vue知识相关推荐

  1. Web前端程序员该如何准备面试?这些面试知识应该掌握

    面试其实是实力和运气并存的事情,所以一方面我们要做好知识的准备,另一方面也要抓住时机,该出手就出手,那么Web前端程序员该如何准备面试呢?下面和一起来看看吧! 一:Web前端面试什么? 针对Web前端 ...

  2. java前台界面设计_前端程序员要懂的 UI 设计知识

    前端程序员要懂的 UI 设计知识 疯狂的技术宅 前端先锋 翻译:疯狂的技术宅 作者:Per Harald Borgen 来源:freecodecamp 正文共:1401 字 预计阅读时间:5分钟 作为 ...

  3. 一个合格的web前端程序员要学会哪些技能?

    想要成为一名合格的web前端程序猿,要学习的东西有很多,那么web前端要学会哪些技能呢?来看看下面的详细介绍就知道了. 一个合格的web前端程序员要学会哪些技能?想从事web前端开发,只会HTML.C ...

  4. 年薪30W前端程序员,需要吃透的前端书籍推荐

    随着互联网时代的发展,web进入2.0时代,前端开发的岗位逐渐独立出来,大量的前端程序员工资和技术水平飙升.前端框架层出不穷,新技术不断更新,作为前端的程序员也是倍感吃力.但为了高薪,每一个前端开发者 ...

  5. 推荐一个Web前端程序员必须要吃透的书籍!

    随着互联网时代的发展,Web进入2.0时代,前端开发的岗位逐渐独立出来,大量的前端程序员工资和技术水平飙升.前端框架层出不穷,新技术不断更新,作为前端的程序员也是倍感吃力.但为了高薪,每一个前端开发者 ...

  6. 初中级前端程序员面试中小型公司会问哪些问题?

    初中级前端程序员面试中小型公司会问哪些问题?不同的公司面试内容也不尽相同,有的面试过程很轻松,有的面试官是个架构师level 挺高不会问八股文,给出了几个现实中的场景,然后转换成代码的逻辑去让实现. ...

  7. 前端程序员和后端程序员有什么不同?我来告诉你薪资待遇差多少

    作为一个程序员,我发现后端程序员和前端程序员有很大的不同.后端程序员主要关注的是处理看不见的部分,如服务器.数据库.API等等.而前端程序员主要关注的是展现的部分,如网页的设计.交互和用户体验等等. ...

  8. 前端程序员的职业发展规划与路线——ChatGPT的回答

    文章目录 一.前端程序员的职业规划是? 回答1: 作为一个前端开发程序员,您的职业发展路线可能如下: 回答2:作为前端开发程序员,您的职业发展路线可能如下: 回答3: 你的职业发展路线可能是这样的: ...

  9. 前端程序员饱和了吗?我们公司给初级前端开到了12K

    故事起因 最近我有个刚毕业的学生问我说:我感觉现在前端行业已经饱和了,也不是说饱和了,是初级的前端根本就没有公司要,哪怕你不要工资也没公司要你,前端刚学出来,没有任何的项目经验和工作经验,根本就不会有 ...

最新文章

  1. R语言break函数和next函数实战
  2. (0013)iOS 开发之集成友盟第三方登录
  3. Halcon初学者知识:用set_paint直观显示图像的属性
  4. uos系统不激活能用吗_国产统一操作系统UOS真的能代替window系统吗? UOS上手体验...
  5. javascript高程3 学习笔记(三)
  6. Android之shape属性详解
  7. 一图看懂云栖大会「云原生」发布
  8. python--编码问题
  9. $.prop()和$.attr() 区别用法
  10. 美团点评技术年货:900+页电子书,覆盖前端、后台、大数据、算法……(附下载链接)...
  11. fossid安装教程_keepalived 邮件通知
  12. java中使用字符(字节)读取文本内容
  13. 一体机的扫描至网络共享的设置
  14. 循环神经网络(LSTM和GRU)(1)
  15. Java反射学习总结终(使用反射和注解模拟JUnit单元测试框架)
  16. 金陵科技学院c语言实验报告册,C语言实验报告册a
  17. 信息学奥赛一本通1142:单词的长度
  18. 前端开发笔记:记一次网站创建的过程
  19. Android视图绘制流程完全解析(二)
  20. OpenFlow——抓包packet_in和packet_out消息

热门文章

  1. float转十六进制
  2. JAVAWEB复习知识六:根据Bootstrap框架做网站首页
  3. 系统学习-----NFS协议
  4. centos7搭建socket5代理服务器
  5. 百度关键词pc端排名查询易语言代码
  6. Socket网络程序设计(4) ———— 实现linux和windows的文件传输
  7. office反应慢解决办法
  8. Vintage表的写法(sql/python)
  9. vcode(visual studio code)中文配置
  10. Geoserve发布Mapbox矢量切片格式openlayer加载案例