• vue面试题


    VUE

    • Vue :数据驱动的M V Vm框架

    • m :model(后台提供数据),v :view(页面),vM(模板)

    • 流程

      • m-》vm-》v
      • m与vm之间通过ajax axios实现数据交互(前后端数据交互)
      • vm(前端拿到数据后,对数据进行处理)
      • v(数据改变后,页面改变)
    • 兼容

      • ie9及其以上(Vue使用Es5)
      • ie8用的是es3
    • 注意

      • 不要将body、html作为挂载点
      • 新建一个div作为挂载点
      • 一个页面中尽量只有一个挂载点
      • 插值等同{{}}{{}},只能与标签内使用)
      • 等同于innerHTML,innerTEXT
      • 慎用innerHTML(会执行之内的代码->xxs攻击)
      • 指令需要放在标签的属性中使用
      • 指令中的双引号会提供一个js运行环境("变量、简单运算")双大括号{{}}具有相同的功能
      • v-text插入的变量作为字符串处理
      • v-html除非是信任的内容不然不要使用
    • v-show控制元素的显示隐藏

      • 初始开销较大,dom一直存在与结构中 如果是需要经常切换的dom 推荐使用该指令
      • v-show只是css级别的显示隐藏=》display:none
      • 在vue中想要显示或隐藏
        • 给data中添加一个属性,其值为布尔类型
        • 将对应值添加个v-show指令
        • 控制这个布尔值,以达到控制显示隐藏的目的
        • true==显示,flse==隐藏
    • v-if

      • 切换开销较大 false情况下 dom不会被渲染
      • v-if是html结构级别的隐藏,直接将对应标签删除
      • v-if、v-else-if、v-else和js中的if else else if一样的(只能满足一级要求,其后不再执行)
    • v-for

      • 用于遍历数组或对象
      • v-for="item in items"
      • v-for="item,index in items" 项+索引 数组
      • v-for="value in items" 值 对象
      • v-for="value,key in items" 键+值 对象
      • v-for="value,key,index in items" 键+值+索引 对象
      • v-for="自定义名字 数组名"
      • v-for可以遍历出index
      • 对象遍历(不常用)
        • v-for="value in 对象名"
        • v-for="(value,key) in 对象名"
        • v-for="(value,key,index) in 对象名"
      • 要遍历那个标签就将指令写给那个标签
      • 建议所有使用v-for指令的标签都添加上:key="惟一值"(后期使用,不建议使用index(虽然也是唯一的))
      • key vue渲染原理 复用元素 没有key的话 当数据顺序发生变化时 如果没有绑定key 只会更新数据(元素不会更新,dom复用)
      • 不建议同时使用v-for和v-if v-for拥有更高的优先级
    • v-bind:绑定

      • 根据数据改变标签的属性(src,href)
      • 将标签的属性与data中的变量绑定
      • v-bind:src="data中的变量名"(将src与data中对应的变量名绑定,当数据改变时,src中的值也随之改变)
      • 使用非常广泛=》简写成为:属性名="data中的变量"
      • 如果要修改标签中的所有属性,可以绑定data中的对象,对象中的属性名,与标签中的属性一一对应(也可以添加其他属性)(可以更方便快捷的改变标签中的多个属性,或添加属性)
      • :style=""->改变标签css样式
        • 阔以是对象,但是值必须加引号(指令双引号间为js执行环境)
      • :class=""->添加类名
        • :class="[box,box1,{box2:flag}]"
        • :class="{class:flag}"
        • 绑定类名可以与普通class属性共存
          • <span class="class1" :class="{class2:flag1}"></span>
    • v-model:双向绑定

      • 上述方法只能实现,数据改变之后,页面内容随之改变,但数据不会在页面内容改变之后随之改变(即单项绑定)
      • 页面内容改变是(form表单元素),Vue数据改变
        <input type="radio" v-model="" v-bind:value="0">
      
      • 将input中的值value绑定为数字0,(指令中的双引号间为js运行环境),再将input与Vue中的数据,双向绑定,其后可以得到值为数字Number类型
    • v-on:绑定事件

      • v-on后跟事件名,等于函数名(methods对象中的方法),有实参加括号,无实参可省略括号
      • 可以通过this.data中的属性名,获取对应的数据
      • v-on:click="",双引号中可直接对data中的数据进行修改
      • v-on:click="methods方法名",由于使用较多,所以向v-bind一样具有缩写,@click="函数名(实参)"
    • 修饰符

      • v-on:click="methods中的方法名"==@click="methods中的方法名"
      • 事件触发具有冒泡机制,如何禁止-》修饰符
      • @click.stop=""=>阻止冒泡
      • @click.prevent=""=>阻止浏览器默认行为

    三了解

    • v-pre:跳过标签编译过程,提升性能

      `<pre>`
        内部代码
        回车
        浏览器编译后
        就是回车
      `</pre>`
      
    • v-clock

      ```<style>
        [v-clock] {
          display:none
        }
      </style>
      ```
      
      • 加载完成之前,具有v-clock的标签隐藏
      • Vue编译完成之后,自动清楚v-clock
    • v-once

      • 只在页面第一次渲染是调用数据
      • 之后不会在跟随数据发生变化

    生命周期

    四大生命周期

    • 顺序(钩子函数的执行顺序,与data同级)
      • 创建-create
        • beforeCreate:创建前(无data中的数据,只有该阶段无法访问到data中的数据)(数据于创建完成之后进行初始化)
        • created:创建完成后
      • 挂载-mount(app.$mount(""))(不用el:"#app"挂载的话,可以用$mount挂载)
        • beforeMount:挂载之前
        • mounted:挂载之后
      • 更新-update(数据发生改变)
        • beforeUpdate:更新之前
        • updated:更新之后
      • 销毁-destroy
        • beforeDestroy:销毁之前(app.$destroy()强制销毁)
        • destroyed:销毁之后
    • 注意
      • 创建和挂载的四个钩子函数只会调用一次
      • 更新周期对应的两个钩子函数,只要数据发生改变就会触发
    • data
      • vue中的数据时响应式的 所以需要在初始化Vue是将需要响应的变量提前声明
    • Object.freeze()
      • 属性放进去,vue不会对其进行追踪变化了
    • v-once
      • 执行一次性的插值 数据改变时,插值处的内容不在更行

    计算属性-computed(对象与data同级)

    • 当遇到比较复杂的语句时,可将其写在computed中
    • computed中的函数不可以调用,而是将其函数名写在{{中}},将其作为data中的属性名
    • 创建时与methods一致,用法与data中的数据一致,对象!!!!
    • 实质:将computed计算的结果return到页面中**
    • 当多次调用同一个computed方法时,会存在缓存问题**,当需要实时更新数据时,可以使用methods(避免缓存)

    监听-watch(对象与data同级)

    • watch:{要监听的值的名字(){},要监听的值的名字:{handler(){},deep:true,//可以监听对象内部属性的改变 immediate:true//页面加载后立马执行第一次监听函数}}
      data:{
    
      },
      watch:{
        //第一种方法(无法监听到对象内部数据变化)
        msg(newValue,oldValue){
          //data中的属性名+()+{},如果msg是对象的话,无法监听对象内属性的变化
          //监听函数有两个参数,分别为新值和旧值
          console.log(newValue,oldValue)
          //该方法无法监听到对象中的数据,只能在变量内存储的地址发生改变时触发(引用类型,栈中存放的是指针,堆中的地址)
        }
        //第二种方法(第一种方法的变形)
        msg:{
          handler(newValue,oldValue){
            console.log(newValue,oldValue)//data中的非对象数据,能够监听变化,并且存在两个数据,即新数据,旧数据
            //仍然监听不到对象中数据的变化
          }
        }
        //第三种方法(添加对应参数)
        msg:{
          handler(){
            console.log("发生了变化")
          },
          deep:true,  //是否监听对象内部数据的变化
          immediate:true  //是否与数据初始化之前设置监听函数
        }
      }
      (详见)[https://cn.vuejs.org/v2/guide/list.html]
      /* 
        由于 JavaScript 的限制,Vue 不能检测以下数组的变动:
    
        当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
        当你修改数组的长度时,例如:vm.items.length = newLength
        ----vm.items[indexOfItem] = newValue
        // Vue.set
          Vue.set(vm.items, indexOfItem, newValue)
        // Array.prototype.splice
          vm.items.splice(indexOfItem, 1, newValue)
        
        Vue 不能检测对象属性的添加或删除
          
       */
    

    过滤器-filters(对象,data同级)

    过滤器的应用范围

    • 双花括号插值和v-bind表达式
    • 过滤器的作用是,对对应的值进行处理-{{数据 | 过滤器名}}
    • v-bind可以添加{{可以添加}}v-text不可以添加
    • 过滤器函数中的参数就是 | 之前的对应的数据,过滤器函数中需要返回新的内容才能显示在页面中(即,过滤器函数中需要存在return)
    • 过滤器可以用多个{{数据 | 过滤器1 | 过滤器2 | 过滤器n}}--(过滤器的添加顺序不同(对数据的处理顺序不同,可能造成,处理后数据结果不同))

    组件

    • 创建
      • complate组件模板
      • vue组件分为两种,一种为全局组件,一种为局部组件,组件需要注册才能使用
      • 注册:Vue.component("组件名",组件配置对象)---》一般将 组件配置对象提取出来,外部配置
    • 使用组件
      • 要在父组件的组件模板中使用对应的组件标签
      • <组件名></组件名>
    • 局部注册
      • 局部注册需要在对应组件中添加components属性
        const 组件名={
          template:"",
          components:{
            局部组件名:组件配置对象//这个组件就只能在当前组件的模板中使用
            //相当与在对应父元素组件中实现注册,为局部组件,只能在该组件中调用,否则报错
          }
        }
    
    • 注意
      • 组件模板中只能有一个根节点
      • 组建的配置对象,一定、一定、一定要放在其注册之前
      • 组件中可以写出el对象外的几乎所有属性
      • 组件中的data为函数,需要将数据return出去,然后可以正常使用,其他无异常
      • 可以通过将组件标签,添加到其父组件的complate中,实现
      • 往组件中添加数据,只能在其对应的complate中添加,在html结构标签中无法添加内容&&将其添加到其父元素的complate中后无法修改其数据
      • 因为HTML不区分大小写,所以在HTMl模板中,标签需要写成纯小写,驼峰命名变成-连字符连接

    通信方式

    • 父子通信

      • 父->子
        • 父子组件通信基本步骤

          1. 在子组件中添加props(对象)
            配置对应prop的名字
          2. 找到对应父组件模板中的子组件标签
            在标签上添加对应prop的名字作为属性 后边跟着要传递的值

          第二步可以传递静态值(固定值) 也可以传递动态值,data中的值
          区别就在于加不加v-bind

          • 注意
            • props:["prop名1","prop名2",……]---》第一种写法,可以有多个prop,即数据通路

            • props:{prop名字:String}/props:{prop名字:[String,Number]}-->即允许传输的数据类型,可以有多个

            • props:

              {prop名字:{type:允许类型,default:默认值,validator(value){验证数据,true//验证通过,否则报错},required:true}}---->type(允许传输的数据类型),default(无传输数据时的默认值),validator(验证传输数据是否满足条件),required:true(true,则该项为必须传输项目)(与default有冲突,有默认项时,即使无数据传输,默认值将作为数据,是否必填无关紧要)
              
        • props中的prop名,可以直接当做data中属性(数据)使用

        • 遍历数组时,需要添加:key="惟一值即可"

      • 子->父
    • 非父子通信

      main.js中 空vue载体
      Vue.prototype.$bus=new Vue()
          在所有的 Vue 实例中可用了,甚至在实例被创建之前就可以
           $ 是在 Vue 所有实例中都可用的属性的一个简单约定。这样做会避免和已被定义的数据、方法、计算属性产生冲突。
           通过 $ 为实例属性设置作用域来避免这种事情发生。你还可以根据你的喜好使用自己的约定,诸如 $_appName 或 ΩappName,来避免和插件或未来的插件相冲突。
      
       需要进行通信的组件
       import $bus from '../../../main';
      
       this.$bus.$on('upload',payload=>{ do somthing })  //先监听
      
       this.$bus.$emit('getPayload',payload)  //后触发
      

    修饰符

    • 事件修饰符,为v-on提供了事件修饰符
      • stop
        • 阻止冒泡
      • prevent
        • 阻止默认行为
      • capture
        • 捕获阶段执行??
      • self
        • event.target 当前元素自身触发时执行函数
      • once
        • 只执行一次
      • passive
        • addEventListener(type,handler,useCapture)-->addEventListener(type,handler,{capture:false,passive:false,once:false})-->是否捕获,是否'顺从'???,是否只执行一次监听(之后自动removeEventListener)
        • passive提高流畅性能
        • 调用preventDefault()无效
    • 按键修饰符,为v-on在监听键盘事件时添加按键修饰符
      • enter .13
      • tab
      • delete
      • esc
      • space
      • up
      • down
      • left
      • right
      • 可以通过全局config.keyCode对象自定义按键修饰符别名
    • 系统修饰键,尽在按下相应按键时才触发鼠标或键盘事件的监听器
      • ctrl
      • alt
      • shift
      • meta
    • exact修饰符允许你控制由精确的系统修饰符组合出发的事件,ctrl+shift等组合键
    • 鼠标按钮修饰符
      • left
      • right
      • middle

    路由router

    • 前后端都能够实现根据url的不同,跳转至指定页面,但实现原理不同
    • 四步骤
      • 一 创建组件配置对象
      • 二 创建routes配置对象(必须是routes,否则虽然不报错,但是也不会有效果)
      • 三 创建router实例(new VueRouter)
      • 四 将router添加进Vue中
    • <router-view></router-view>(url对应的组件,将替换掉该组件,即该组件不会显示到页面中)
      • <router-link to="/" tag="li">,该标签渲染到页面中时会被a标签替换,to中将会是替换后的url,tag可以改变渲染后router-link的结果(可以改变成为其他标签,通过js实现相应的链接跳转),激活状态的链接会具有router-link-active(该类名不够精确)---》推荐使用router-link-exact-active来为激活状态的标签添加对应的类名
      • linkExactActiveClass:'active',通过该全局配置,实现类名的替换var router=new VueRouter({//new VueRouter大括号中为全局配置 linkExactActiveClass})
      • 点击对应router-link标签,to到新的url后,显示对应的组件,实现页面的跳转(数据的改变)但域名不会改变

    动态路由

      1. 配置路由时可以使用动态路由{path:"/a/:id"}
      • 通过$route.params.id来获取对应的id,根据id获取数据,并改变显示内容
      • 通过为$route设置监听函数,来实现当url改变时,发送新的请求,获取数据后渲染到页面的操作,可以为其添加immediate属性,实现页面首次加载就发出请求
      • 如果动态路由想要使用a标签跳转,必须给路由添加一个name属性并使用名字进行跳转
        • <router-link :to="{path: '/demo', params: {id: 1}}">链接</router-link>
      1. 使用?id=xx的形式--query
      • 配置路由时使用基本配置方式
      • 将query值添加到路由的最后使用?xx=值的形式添加?xx=值&xx=值
      • 通过$route.query.xx来获取

    动态路由与静态路由的区别

    • 二者无实质区别(都是根据url不同,获取数据渲染到页面中)
    • 获取方式的差别
      • 动态路由获取--$route.params.xxx与配置对象中routes[{path:"/:xxx"}]--只需要xxx一致即可---当使用router-link :to="{name:'',params:{xxx:''}",只需要v-bind:to即可,否则获取到的是字符串--(需要使用name)
      • 静态路由--$route.query.xxx与链接中router-link to="/?xxx=xx"

    原理

    • 通过切换url,获取数据,更换div中的内容
    • 后端为主--原始模式
      1. 查找dns服务器,dns服务器返回对应的ip地址
      2. 根据ip地址找到服务器
      3. 服务器后台根据url提取数据
      4. 根据提取的数据去数据库中查找数据
      5. 将数据渲染到模板中的页面
      6. 返回浏览器
      • 前端只负责提供静态页面模板,供后端渲染数据
    • 前端为主--Vue--M、V、VM
      1. 查找 dns服务器,dns服务器返回对应的ip地址
      2. 根据ip地址找到服务器
      3. Vue根据传来的url提取数据
      4. Vue根据数据发送请求(ajax请求),将查询数据发送给后台
      5. 后台接受到数据后,查询数据,返回查询到的数据
      6. Vue接收到数据后,渲染到模板中
      7. 浏览器显示
    • 优缺点
      • 前端渲染
        • 速度快,减轻服务器压力,交互较好(loading等),不借助某些技术无法进行seo优化
      • 后端渲染
        • 便于seo优化,访问到的内容都在页面中

    动态路由

    • 动态路由获取
      • 模板中
        • $route.params.x
      • js
        • this.$route.params.x
      • watch
        • to.params.x
    • 重定向
      • a跳转到b
        • 给a设置redirect--》b的路由
    • 别名
      • 当访问/a时,实际访问到的内容为b时,url显示为/a
        • 应该给/b加alias"/a"
    • 命名视图
      • 同级展示多个视图,而不是嵌套展示,可以使用命名视图
      • 一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件

    路由组件传参

    • 在组件中使用$route会使之与对应路由形成高度耦合,从而使组件只能在某些特定的url上使用,限制了灵活性,可使用props将组件和路由解耦
    • { path: '/user/:id', component: User, props: true }routes中设置props为true时,默认传递$route.params
      • 组件配置对象中,可直接添加props属性,为其添加所需prop即可(如:id、tab等)
    • 你可以创建一个函数返回 props。这样你便可以将参数转换成另一种类型,将静态值与基于路由的值结合等等。
      • { path: '/search', component: SearchUser, props: (route) => ({ query: route.query.q }) }
      • 该返回对象将作为属性,传递给对应组件

    HTML5 History模式

    • 使用history模式,可以使得URL像正常url(去掉#号)

    导航守卫--》路由导航守卫--》路由钩子函数

    • 所有的路由都会经过全局导航守卫,所以在网页需要登录等操作才能访问时使用**
    • this.$route.query.xxx---->js函数中通过,获取url中查询字符串信息,此处为跳转至该页面的源页面
    • 通过this.$router.push(url)---->实现跳转至来时页面---》即登录过后跳转至页面
    • router.beforeEach((to,from,next)=>{}),(from来源,to去向,next守卫),to.fullPath(其中存放着url路径及查询字符串)
    • meta属性routes中添加对应属性,to.matched其中存放着当前网页的路径,以及其祖先url信息,可在其中找到对应的meta,运用数组some方法(存在该meta,即需要验证的页面)

    全局解析守卫

    • beforeEach**
    • 类似router.beforeEach
    • 区别,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用

    全局后置钩子

    • afterEach((to,from)=>{})
    • 只有to,from**,不接受next函数,也不会改变导航本身

    路由独享守卫

    • beforeEnter**
    • 在路由配置(routes)上直接定义
    • 与全局前置守卫的方法参数一样

    组件内守卫

    • beforeRouteEnter
      • 在渲染该组件的对应路由被confirm前调用
      • !不能 !获取组件实例this----可以通过beforeRouteEnter(to, from, next) { console.log(this, 'beforeRouteEnter'); // undefined console.log(to, '组件独享守卫beforeRouteEnter第一个参数'); console.log(from, '组件独享守卫beforeRouteEnter第二个参数'); console.log(next, '组件独享守卫beforeRouteEnter第三个参数'); next(vm => { //因为当钩子执行前,组件实例还没被创建 // vm 就是当前组件的实例相当于上面的 this,所以在 next 方法里你就可以把 vm 当 this 来用了。 console.log(vm);//当前组件的实例 }); }---vm---vue官方使用--vue的实例---间接使用this
    • beforeRouteUpdate--2.2新增
      • 在当前路由改变,但是该组件被复用时调用--即虽然路由改变,但访问的仍然是同一个页面
      • 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
      • // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
      • 可以访问组件实例 this
    • beforeRouteLeave
      • 导航离开该组件的对应路由时调用
      • 可以访问组件实例this

    完整的导航解析流程--官方(并非所有步骤都会执行)

    1. 导航被触发
    2. 在失活的组件里调用离开守卫
    3. 调用全局的beforeEach守卫
    4. 在重用的组件里调用veforeRouteUpdate
    5. 在路由配置里调用beforeEnter
    6. 解析异步路由组件
    7. 在被激活的组件里调用beforeRouteEnter
    8. 调用全局的beforeResolve守卫
    9. 导航被确认
    10. 调用全局的afterEach钩子
    11. 触发DOM更新
    12. 用创建好的实例调用beforeRouteEnter守卫中传给next的回调函数

    守卫与生命周期钩子函数的执行顺序

    • 全局 3
      • beforeEach
      • beforeResolve
      • afterEach
    • 路由独享 1
      • beforeEnter
    • 组件内 3
      • beforeRouteEnter
      • beforeRouteUpdate
      • beforeRouteLeave
    • 导航守卫和声明周期钩子函数的执行先后顺序
      • 访问路由时
        • 全局守卫beforeEach先执行
        • 路由独享守卫beforeEnter执行
        • 组件内守卫beforeRouteEnter执行
        • 全局解析守卫beforeResolve执行
        • 最后全局后置守卫afterEach执行
        • 声明周期钩子函数执行
    • 切换路由时,如果路由是动态路由

      • 全局守卫beforeEach调用
      • 组件内守卫beforeRouteUpdate调用
      • beforeResolve调用
      • afterEach
      • // 如果数据也发生了变化,在路由结束后触发
      • beforeUpdate
      • updated
    • 切换路由时,路由不同

      • from befreRouteLeave
      • beforeEach
      • to 路由独享守卫beforeEnter
      • to 组件内守卫 beforeRouteEnter
      • 全局解析守卫beforeResolve
      • 全局后置守卫 afterEach
      • to 组件生命周期钩子,知道to组件创建完成
      • 销毁from的组件
      • to 组件挂载
    • 当组件切换时,先创建新组件,当新组件beforeMount(生命周期钩子函数-挂载前)之后,才销毁旧组件,旧组件销毁后,新组件被挂载

    • 生命周期钩子函数永远在路由afterEach之后执行

    过渡动效

    • 过渡动效
      • 为router-view标签,添加transition标签
    • 单个路由的过渡
      • 给路由组件设置过渡效果,路由组件内使用transition,并设置不同的name属性
    • 基于路由的动态过渡
      • 基于当前路由与目标路由的变化关系,动态设置过渡效果
      • 基于路由变化使用对应的name值,实现路由不同,过渡效果的不同
    • Vue在插入、更新或则移除DOM时**,提供多种不同方式的过渡效果
      • 在css过渡和动画中自动应用class
      • 配合使用第三方css动画库,如Animate.css
      • 在过渡钩子函数中使用JavaScript直接操作DOM
      • 配合使用第三方JavaScript动画库,如Velocity.js
    • 单元素/组件的过渡
      • 条件渲染(使用v-if
      • 条件展示(使用v-show
      • 动态组件
      • 组件根节点

    • 当插入或删除包含在transition组件中的元素时
      1. 自动嗅探目标元素是否应用了css过渡或动画,如果是,在恰当的时机添加/删除css类名
      2. 如果过渡组件提供了JavaScript钩子函数,这些钩子函数将在恰当的时机被调用
      3. 如果没有找到JavaScript钩子并且也没有检测到css过渡/动画,DOM操作(插入/删除)在下一帧中立即执行。(注意:此指浏览器逐帧动画机制,和Vue的nextTick概念不同
    • 类名-六个class
      1. v-enter:定义过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除
      2. v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除,这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数
      3. v-enter-to:2.1.8版及以上定义进入过渡的结束状态,在元素被插入之后下一帧生效(于此同时v-enter被移除),在过渡/动画完成之后移除
      4. v-leave:定义离开过渡的开始状态,在离开过渡被触发时立刻生效,下一帧被移除
      5. v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数
      6. v-leave-to:2.1.8版及以上定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效(与此同时v-leave被删除),在过渡/动画完成之后移除
      • 对于这些过渡中切换的类名来说,如果使用一个没有名字的<transition>,则v-是这些类名的默认前缀。如果使用了<transition name="my-transition">,那么v-enter会替换为my-transition-enter,即替换为transition标签中的name属性的值
    • 自定义过渡的类名
      • enter-class === v-enter
      • enter-active-class === v-enter-active
      • enter-to-class === v-enter-to
      • leave-class === v-leave
      • leave-active-class === v-leave-active
      • leave-to-class === v-leave-to
      • 添加到transition标签中,修改对应类名
      • 他们的优先级高于普通的类名,这对于Vue的过渡系统和其他第三方css动画库,如Animate.css结合使用十分有效
      • 不再需要为transition标签添加name属性
    • 同时使用过渡和动画
      • Vue 为了知道过渡的完成,必须设置相应的事件监听器。它可以是 transitionend 或 animationend ,这取决于给元素应用的 CSS 规则。如果你使用其中任何一种,Vue 能自动识别类型并设置监听。

      • 但是,在一些场景中,你需要给同一个元素同时设置两种过渡动效,比如 animation 很快的被触发并完成了,而 transition 效果还没结束。在这种情况中,你就需要使用 type 特性并设置 animation 或 transition 来明确声明你需要 Vue 监听的类型

    Vueg插件

    • 为webApp提供转场特效的开源Vue插件
    • Vueg

    Vuex-状态管理模式

    • 借鉴The Elm ArchitectureReduxFlux,与其他模式不同的是,Vuex是专门为Vue.js设计的状态管理库,以利用Vue.js的细粒度数据响应机制来进行高效的状态更新

    • 什么情况下使用Vuex

      • 如果不开发大型单页应用,使用Vuex可能是繁琐冗余的
      • 如果应用够简单,最好不要使用Vuex,简单的store模式足够了
    • Vuex与单纯的全局对象的区别

      1. Vuex的状态存储是响应式的,当Vuex组件从store中读取状态的时候,若store中的状态发生变化,那么相应的组件也会相应的得到高效更新
      2. 不能直接改变store中的状态,改变store中的状态的唯一途径就是显示的提交(commit)mutation,这样使得我们方便的追踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好的了解我们的应用
    • State

      • 可以在需要使用store中数据的组件的computed中新建对应state中数据的方法,将state中的数据返回即可直接使用computed:{msg(){return this.$store.state.xxx}}
      • mapState-辅助函数
        • 当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余,使用mapState辅助函数帮助我们生成计算属性
        • computed:mapState({count:state=>state.count,countAlias:"count"})-->使用箭头函数可使代码更简练,但有时为能使用this获取局部状态,必须使用常规函数--但是这种写发造成非store相关数据无法写入
        • 对象展开运算符
          • 使用对象展开运算符将此对象混入到外部对象中computed:{localComputed(){},...mapState({})}
    • Getter

      • 从store的state中派生出一些状态
      • getter接收state作为第一个参数,也可以接收其他getter作为第二个参数
      • 通过让getter返回一个函数,实现getter传参,getter在通过方法访问时,每次都会进行调用,而不会缓存结果
    • Mutation--提交

      • 更改Vuex的store中的状态的位移方法是提交mutation。Vuex中的mutation非常类似于事件,每个mutation都有一个字符串的事件类型(type)和一个回调函数(handler)。这个回调函数就是我们实际进行状态更改的地方,并且会接受state作为第一个参数
        • 触发。this.$store.commit('xx')
        • 提交载荷(payload)。mutations:{xxx(state,n){}}--state作为第一个参数,第二个参数为载荷,大多数情况下载荷应该是一个对象
        • 对象风格的提交。this.$store.commit({type:'xxx',cs:xx})--type即为mutations中的事件名,其他均为参数
      • Mutation需遵守Vue的响应规则
        1. 最好提前在store中初始化所有所需属性
        2. 当需要在对象上添加新属性时,应该:
          • 使用Vue.set(obj,'newProp',123),或者
          • 以新对象替换老对象。state.obj={...state.obj,newProp:123}
      • 使用常量替代Mutation事件类型
        • 使用常量替代mutation事件类型在各种Flux实现中是很常见的模式。这样可以使linter之类的工具发挥作用,同时把这些常量放在单独的文件中可以让你的代码合作者对整个app包含的mutation一目了然 ,--即将mutation中的事件名作为一个对象的属性存入对象中[obj.name]作为mutation中的事件名,可以更直观的了解各事件的功能
      • Mutation必须是同步函数
      • 在Vuex中,mutation都是同步事物
    • Action--分发

      • Action类似于mutation,不同之处在于:
        1. Action提交的是mutation,而不是直接变更状态
        2. Action可以包含任意一步操作
      • actions:{xxx(context){context.commit('xxx')}}--actions中处理的都是异步操作,改变数据时最后一步都是调用mtation即context.commit()
      • 使用参数解构/解构赋值来简化代码(特别是需要调用commit很多次的时候)--actions:{xxx({commit}){commit('xxx')}}--通过结构复制直接得到context中的commit调用mutation中对应的事件处理
      • 触发
        • this.$store.dispath('xxx')
      • 因为mutation中只能执行同步操作,所以只能通过actions内部执行异步操作后调用mutation--actions:{xx({commit}){setTimeout(()=>{commit('xxx')},1000)}}--一秒后调用commit('xx')执行mutation中的对应处理事件
      • Actions支持同样的载荷方式和对象方式进行分发
    • module

      • 模块中有自己的state,将其放入store的modules中后,其state会变成rootState(最外层store中的state)
        • this.$store.state.模块名 //这就是对应模块中的state对象
      • getters最终会变成root中的getters
        • module={getters:{getter名字(state,getters,rootState,rootGetter){}}}--state是当前模块的状态,rootState是根store的state
        • 如果没有namespaced:true属性那么getter就是rootstore的getter,如果有该属性getters就是模块中的getter,第四个参数rootGetter才是全局中全部的getter
        • this.$store.getters.getter名字
        • 如果给模块添加namespaced:true那么对应的getter,mutation,action都会变成“对应模块名/对应名字”--区分rootstore与模块中的getter,mutation,action
        • 如果模块中有namespaced属性,那么commit('mutation')只能触发模块内的mutation
          • 如果在commit第三个参数中添加{root:true}-则触发的是全局的mutation--commit('mutation名字',payload,{root:true})--dispatch同理
        • 模块创建
          • new Vuex.Store({modules:{模块名:{}}})
          • 分开--const module={} new Vuex.Store({modules:{模块名:module}})
          • 模块中也有state,getters,mutations,actions,modules
          • 单个模块当做一个store即可
            • state
              • this.$store.state
                • 模块中的state
                  • this.$store.state.模块名
            • getters,actions,mutations--直接会添加到rootstore中的对应位置
            • 如果给模块添加namespaced:true
              • name对应的getters,mutations,actions会变成 模块名/名字 的形式,并且可以与rootstore中的姓名重合,因为名字之前带有各自模块名
                • 同时,直接在模块中commit('mutation')/dispatch('action'),默认提交/分发的是模块中的mutation/action
                • 想要调用全局,需要在之后加上{root:true}
                  • commit('mutation',payload,{root:true})
                  • dispatch('action',payload,{root:true})
            • 辅助函数如果想要使用命名空间模块中的内容
              • mapState({msg:state=>state.模块名.msg})
              • mapState('模块名',['msg'])
    • 代码

      var store = new Vuex.Store({
        state:{
    
        },
        mutations:{
    
        },
        getters:{
    
        },
        actions:{
    
        }
      })
      this.$store.state.xx  //获取state中存储的数据
    
    • input v-model处理方法**
      • 详见Vuex-表单处理
      • 当页面中存在input等表单元素时,需要使用v-model,但store中state无法与computed直接修改
      • 所以将computed的书写格式写成computed:{msg:{get(){//获得state中的数据},set(value){//value 当页面中form表单中的数据发生变化时触发,值即为修改后的数据 可在此提交mutation修改state中的对应数据 this.$store.commit('setMsg',value)}}}
      • computed对象中的get方法用来获取store里state中的数据,显示到页面,而set方法中的value则为页面中表单数据发生变化后的值,可在触发后将值作为载荷提交mutation修改state中的数据
    • axios拦截器**
      • 在请求或响应thencatch处理前拦截它们
      • 对发送前数据添加token,或设置请求头,验证等
      • 对响应数据做处理,剥离外层结构等
        //添加请求拦截器
        axios.interceptors.request.use(function(config){
          //在发送请求之前做些什么
          return config;
        },function(error){
          //对请求错误做些什么
          return Promise.reject(error);
        });
              // axios.interceptors.request.use(config=>config,error=>Promise.reject(error))
        //添加响应拦截器
        axios.interceptors.response.use(function(response){
          //对响应数据做点什么
          return response;
        },function(error){
          //对响应错误做点什么
          return Promise.reject(error);
        })
              /*
                axios.interceptors.response.use(response=>response,error=>Promise.reject(error))
              */
    
    

    keep-alive

    • 切换组件外层添加<keep-alive></keep-alive>可以缓存组件的状态,当再次切换后显示之前的状态--默认情况下组件被v-if隐藏后经历destroy周期,再次显示时触发create,mount周期,不会保留之前的访问状态
    • 属性
      • include 符合条件的组件会被缓存
        • 字符串
          • 逗号隔开组件
        • 正则
          • 符合比正则表达式的会被缓存--v-bind:include
        • 数组
          • ['组件名','组件名']
          • v-bind:include
      • exclude与include相仿,符合条件的不会被缓存
    • Props:
      • include-字符串或正则表达式,只有匹配的组件会被缓存
      • exclude-字符串或正则表达式,任何匹配的组件都不会被缓存
    • 用法
      • <keep-alive>包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和<transition>相似,<keep-alive>是一个抽象的组件:它自身不会渲染一个DOM元素,也不会出现在父组件链中。当组件在<keep-alive>内被切换,它的activateddeactivated这两个声明周期钩子函数将会被对应的执行
      • 主要用于保留组件状态或避免重新渲染
      • include、exclude--匹配检查先检查组件自身的name选项,如果name选项不可用,则匹配他的局部注册名称(父组件components选项的键值)。匿名组件不能被匹配
      • activated--keep-alive组件激活时调用
      • deactivated--keep-alive组件停用时调用
      • 由于keep-alive的组件缓存,切换组件时不会触发对应的destroy,create,mount周期函数

    ref

    • ref可以添加在组件或者html标签上
    • 可以通过this.$refs.自定义名字获取
    • created生命周期中无法获取DOM,因为created时页面还没有渲染
    • ref加在html标签上,得到对应的DOM对象
    • ref加载组件标签上,得到的是对应组件的组件对象

    nextTick

    • this.$nextTick(()=>{//这里的代码会在每次更新后,页面DOM更新后才会触发})

    对象操作

    • 如果对象某个值不存在,先要添加新的值,并试数据响应--不能使用app.对象.新属性=值
    • 需要使用Vue.set方法
      • Vue.set(对象,'属性','值')
      • app.$set(对象,'属性','值')
      • Vue.delete(对象,'属性')
      • Vue.$delete(对象,'属性')

    自定义指令

    • 想要对DOM元素进行原生操作时,可以使用自定义指令
    • Vue.directive('指令名(不加v-)',{})
    • 自定义指令共5个钩子函数
      • bind
      • inserted
      • update
      • componentUpdated
      • unbind
    • 参数
      • el 指令绑定的元素的DOM对象可以直接操作DOM
      • binding
        • name 指令名
        • value 指令后等于的值 v-指令名='value'
        • oldValue 仅在update和componentUpdated中存在
        • expression 指令表达
        • arg 参数 v-on:click click就是参数
        • modifiers v-on:click.stop stop就是修饰符
          • 修饰符可以有多个,所以修饰符是一个对象
        • vnode Vue 产生的虚拟节点
        • oldVnode 上一个虚拟节点

    slot插槽

    • 正常情况下template中,标签中的内容会被忽略,而slot标签相当于,预留的插槽,可以实现内容的正常显示
    • 在两slot标签中的内容会被当做默认值,即当后期不插入内容时,显示默认值
    • 优点:方便后期组件使用,和更改对应信息

    具名插槽-name属性

    • slot标签有多个时,为避免混乱,可以为其添加name属性
    • 当使用时,可以在标签中添加slot属性,其值为对应slot名-(造成多余标签)
    • 可以通过<template slot="slotname"></template>来实现,该标签不会显示在页面中

    默认内容

    • 当在slot标签之间填写内容时,会被当做默认内容,当不在组件标签之间填写内容时,显示默认内容,填写则覆盖默认值
    • 具名标签slot标签之间添加默认内容无效
    • 具名插槽会与具有slot属性的标签一一对应,多余的内容会在不具名slot中统一显示,如果不存在该标签,则内容舍弃

    作用域插槽(flot-scope="自定义名字")

    • 改变从子组件获取的数据结构???

    • 创建组件时

      • 在slot标签上添加的属性
      • <slot 数据名="值" 数据名2="值2"></slot>
      • 使用组件时,会出现在组件标签内部的slot-scope上
        <组件标签>
        • div slot-scope="自定义名字"">
        • // 自定义名字就是一个对象,对象上包含了所有的slot标签上的属性
        • /div>
        • </组件标签>
    • 作用域插槽的意义

      • 将数据给对应的组件,让使用组件的人可以自定义组件的模板

    @click==v-on:click

    • 写在template中的v-on:click(click事件)可以正常触发
    • 但是,当写在组件标签中时,会被当做是监听(自定义事件名)**
    • 所以**,如果想要在组件标签中写@click事件,可以使用修饰符.native--》声明该click为原生click事件
    • 或者在template中,为@click添加自定义事件,即子到父通信,可传递数据,否则无法触发click事件**

    Element UI-》组件库

    vue-cli

    • 命令行工具
      • Vue 提供了一个官方的 CLI,为单页面应用快速搭建 (SPA) 繁杂的脚手架。它为现代前端工作流提供了 batteries-included 的构建设置。只需要几分钟的时间就可以运行起来并带有热重载、保存时 lint 校验,以及生产环境可用的构建版本。更多详情可查阅 Vue CLI 的文档
      • 安装步骤
        • cnpm install -g vue-cli--(全局安装vue-cli)
        • vue init list name path--(初始化 vue init list(模板类型-通过vue-list查看) name(项目名) path(不写,默认为当前路径))
        • vue init webpack + 项目名称(不能包含大写)
      • 创建
        • ? Project name 输入项目名称

        • ? Project description 输入项目描述

        • ? Author 作者

        • ? Vue build 打包方式,回车就好了

        • ? Install vue-router? 选择 Y 使用 vue-router,输入 N 不使用

        • ? Use ESLint to lint your code? 代码规范,推荐 N

        • ? Setup unit tests with Karma + Mocha? 单元测试,推荐 N

        • ? Setup e2e tests with Nightwatch? E2E测试,N

      • 运行
        • 进入对应文件,路径
        • cnpm install--(安装所需组件)
        • npm start/npm run dev
      • 编写
        • sc--快捷生成template script style结构
      • 插件
        • Vetur


    作者:wudongyu
    链接:https://www.jianshu.com/p/eb4c36319cd4
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    SpringCloud(四)GateWay网关
    C++中的间接宏函数
    一个C++引用库的头文件预编译陷阱
    谈谈C++中的数据对齐
    在C++中实现aligned_malloc
    WPF中的DesignerProperties
    在.NET 6中使用DateOnly和TimeOnly
    在 Ubuntu 上安装 .NET SDK 或 .NET 运行时
    Microsoft Build 2021第二天
    Microsoft Build 2021大会开始后,Develop Blog一系列更新
  • 原文地址:https://www.cnblogs.com/lgnblog/p/11834380.html
Copyright © 2020-2023  润新知