vue进阶

180 阅读6分钟

vue基础部分主要由vue的语法 标签 数据绑定 vue文件部分组成,组件 计算属性,过滤器,监听等组成。可以参考官网 vue vue主要的两大特征:数据驱动视图和组件化

vue声明周期

lifecycle.png 如上图所示vue的的声明周期可分为这几个部分:

  1. beforeCreate 初始化界面之前:在当前的阶段数据和方法都不能访问

  2. created 初始化界面之后:在这个节点vue的实例已经创建 我们可以访问到属性和方法,但是更新数据的时候不会触发updated的函数,也不会更新视图,因此改该段 dom还没有挂载,在该阶段可以进行数据的获取

  3. beforeMount 挂载之前:该阶段可以访问到数据和方法 同样更新的时候不会造成页面的更新,因为此时 虚拟dom已经创建完成 还没有转成真实的dom

  4. mounted 挂载完成:该阶段虚拟dom已经转成真实的dom 并挂载到页面上,在该阶段可以进行dom的操作或者节点等(建议数据的请求放在该节点,因为对于服务端渲染来说,只有beforecreate和created两个阶段,服务端的数据是直接获取到的用来渲染页面的,在created中获取数据的话,对服务端来说会出现数据获取重复的问题

  5. beforeUpadte 更新数据前 : 组件数据更新之前调用,数据都是新的,页面上数据都是旧的 组件即将更新,准备渲染页面 , 可以在当前阶段进行更改数据,不会造成重渲染

  6. updated 组件更新后 : render重新渲染 , 此时数据和界面都是新的 ,要注意的是避免在此期间更改数据,因为这可能会导致无限循环的更新

  7. beforeDestroy 组件卸载前 : 实例销毁之前,在当前阶段实例完全可以被使用,我们可以在这时进行善后收尾工作,比如清除计时器

  8. destroyed 组件卸载后 : 组件已被拆解,数据绑定被卸除,监听被移出,子实例也统统被销毁。

  9. activited keep-live专属,组件被激活时调用

  10. deactivated keep-alive专属,组件被销毁的时候调用

插槽

1.默认插槽 组件外部维护参数和结构,内部安排位置

<!--组件 testSlot-->
<template>
<div>
<slot></slot>
</div>
</template>

<!--使用slot-->
<test-slot>
 <p>我是显示默认插槽的信息</p>
</test-slot>

具名插槽

以name作为插槽的身份标识,从而在组件内部可以区分

<!--组件 testSlot-->
<template>
<div>
<slot name='heaer'></slot>
<slot></slot>
<slot name='footer'></slot>
</div>
</template>

<!--使用slot-->
<test-slot>
 <p>我是显示默认插槽的信息</p>
 <p v-slot:header>我是具名插槽header</p>
  <p v-slot:footer>我是具名插槽footer</p>
  <!--对于之前的vue版本具名插槽还支持-->
   <p slot="header">我是具名插槽header</p>
  <p v-slot="footer">我是具名插槽footer</p>
</test-slot>

插槽作用域

组件外部使用组件内部的数据

<!--组件 testSlot-->
<template>
<div>
<slot name='heaer' :test="info"></slot>
<slot></slot>
<slot name='footer' :test="info"></slot>
</div>
</template>
<script>
export default{
data(){
return {
info:{
header:"header",
footer:"footer"
}

}
}
}
</script>

<!--使用slot-->
<test-slot>
 <p>我是显示默认插槽的信息</p>
 <p v-slot:header="scope">我是具名插槽{{scope.info.header}}</p>
  <p v-slot:footer='scope'>我是具名插槽{{scope.info.footer}}</p>
  <!--对于之前的vue版本(2.6版本)具名插槽还支持-->
   <p slot="header" slot-scope="scope">我是具名插槽{{scope.info.header}}</p>
  <p v-slot="footer" slot-scope="scope">我是具名插槽{{scope.info.footer}}</p>
  
  <!--插槽解构-->
   <p v-slot:header="{info}">我是具名插槽{{info.header}}</p>
  <p v-slot:footer='{info}'>我是具名插槽{{info.footer}}</p>
</test-slot>

模板数据处理

  1. watch 或者computed

利用监听和计算属性的方式对于数据进行二次的加工处理。相应流过于复杂

  1. methods 函数 利用函数进行数据的二次处理,缺点无法进行数据的响应式

  2. 过滤器filters(推荐) 利用filers过滤器对于数据进行处理,在过滤器中获取不到vue实例。只是一个功能性函数。

  3. 通过v-html的方式实现

<div v-html="a>12?12:'错误'"></div>

jsx

jsx是javascript的一种扩展的语法。在jsx语法中我们可以写javascript的语法 还可以写html 当jsx遇到<>的时候则通过html解析,当遇到{}的时候则通过javascript解析。 vue中大部分情况下我们使用的是模板语法的方式去编写组件,但是有时候为了提高渲染速度 , 我们也使用jsx去编写组件。jsx通过render()函数来渲染组件。在jsx中没有插槽的概念,我们可以定义节点来替换插槽,同时在jsx中不能使用 v-*的语法 对于组件传递或者样式动态绑定的话直接属性绑定即可,点击事件用onclick

//item.vue
<script>
export default {
 data(){
 return {
 mes:"jsx",
  color:"red",
      tootle:false,
 testList:['语文''数学','英语','其他']
 
 },
 methods:{
  tootlehandle(){
       this.tootle=!this.tootle   
       this.color='pink'
      }
 },
 render(){
 //定义节点
 const nodetset=(<div>{this.mes=='jsx'?'测试':'其他'}<div>)
 //必须返回一个根标签 里面的变量用{}使用    js语法也用{}进行包裹
 return (<div>
  <button onclick={this.tootlehandle}>切换</button>
 <ul>
 {this.testList.map((item,index)=>{   ///因为forEach 注重执行没有返回值 所以用的是map进行循环
 return(<li class={{'test':this.tootle}} style={{color:this.color}} key={index}>{item}
 {nodetset} //使用定义的节点
 </div>)
 })}
 </ul> 
 </li>)
 }
 }

}

</script>

jsx实现v-model的数据双向绑定

export default{
data(){
return{
test:"wewe"
}
},
methods:{
handleInput(e){
this.test=e.tartget.value
}

},
render(){
return(
<div>
<input oninput={this.handleInput} value={this.test}/>
<span>{this.test}</span>
</div>
)
}
}

jsx的好处,劣势 vue的编译路径:template=>render=>vm.reader=>diff=>vue优化的性能方案 好处:可以使用后js的方式去取编写代码 ,没有template的约束 使用起来更加灵活 劣势:对于大的组件使用jsx编写的话,可能会造成性能问题,因为在template到render的过程中 vue官方做了很多性能优化 这个过程会通过optimize优化ast树

组件化

组件是可被复用的vue实例。

模板组件
Vue.component('组件名称',{
template:'<div>组件</div>',
data(){
return {}
},
methods:{
}
})

mixin -逻辑抽离(抽离公共逻辑等)

多组件使用相同的逻辑或者数据的话我们可以通过混入的方式去将数据或者方法加载到对应的组件中

export default{
 data(){
 return {
  test:"mixindata"
 }
 },
 methods:{
 chanageTest(){
 console.log('mixinChange')
 }
 }
}
///使用的时候
import testMinx from './mixin'
mixins:[testMinx]

混入规则:

  1. data数据混入 data数据的混入 如果键值名冲突的,取组件的键值对。

2.对象混入 值为对象的选项,例如methods、components.和directives 将被合并为同一对象,两个对象键值名冲突时,取组件的键值对。

3.声明周期混入 声明周期混入的,先执行混入在执行组件的声明周期。 extends和mixins的用法基本相同 区别:mixins的类型是数组,extends是变量,合并优先级 组件>mixin>extend 声明函数extend>mixins

vue.extend

vue.extend()可以去创建一个模块 然后再组件中去使用对应拓展的功能

const  testExtend=Vue.extend({
data(){
return{
 test:"我是拓展的数据"
}
},methods:{
  handleTest(){
  console.log('我是拓展的方法')
  }
}
})
//其他组件使用
export default {
import testExtend from './vueextend'
const  tset = new testExtend()//使用  vue.extend()的声明周期比组件的声明周期先执行
created(){
test.handleTest() ///我是拓展的方法

}

}

Vue.use 插件

vue.use是将外部的组件或者第三方的组件通过注册的形式,注册到整理的vue的实例中。对于重复注册的话,vue.use会进行一个去重的操作

import elementui form 'element-ui'
Vue.use(elementui) //注册
手写vue.use(插件名称,options)插件

vue.use 的插件分为函数形式和对象形式两种,如果是函数形式的话则在注册的时候会直接调用函数插件,如果是对象形式的话,则会调用对象中的install方法 然后执行插件的逻辑

//函数插件

export default function(vue,options){
 console.log(vue,options) //默认第一个参数是vue对象,后面的参数则是我们vue.use('插件名',参数)的参数

}
export default {
  `install`:function(vue,options){ //默认第一个参数是vue对象,后面的参数则是我们vue.use('插件名',参数)的参数
    console.log(vue,options)
    vue.prototype.$post=function(){}///post 请求挂载
   
   }

}

组件的引用

  1. 组件的递归引用 tree组件中的子组件的递归嵌套引用

  2. 组件的异步引用

1. components:()=>import('组件地址')
2.components:resolve=>require(['组件地址'],resolve)
  1. 动态组件
<component :is='name' ></component>

routeroute和router 的区别

router是一个由vuerouter构造函数得到的一个router的实例对象,这个对象是一个全局的对象,身上挂载着注册路由的所有属性。一般在该对象中进行路由的跳转,router 是一个由vuerouter构造函数得到的一个router的实例对象,这个对象是一个全局的对象,身上挂载着注册路由的所有属性。一般在该对象中进行路由的跳转,router.push() router.replace()的等router.replace()的等 router 是一个跳转路由的路由对象,每一个路由都对应一个$route的路由对象,该对象包含 跳转路由的名称 路径 参数 meta等信息 一般通过该对象或者name params path,query都等

动态路由

我们可以通过addRoute()和reomveRoute()的方式来对于路由对象进行动态的改变

import vue form 'vue'
import Router from 'vue-router'
vue.use(Router)
export default{
new Router({
 scrollBehavior: () => ({ y: 0 }),
 routes:[
     { path: "/404",
     component: () => import("@/views/404"),
     hidden: true},
      { path: "*", redirect: "/404", hidden: true }
    
    ]
})
}


///使用
import vueRouter form 'router/index'
//添加路由
vueRouter.addRoute({ path: '/about', component: About })