VUE2学习总结

0. render 函数:用来渲染模板的

render (createElement, context) {
  // 渲染模板返回的值就是页面展示的效果
  return createElement('h1', '标签1')
}

1. 交给vue进行管理的函数,一般格式写this对象会指向vm,写成箭头函数this则会指向window;不是vue管理的函数,一般写成箭头函数则会指向vm,写成一般格式则会 指向window

2. Vue.set()

在对现有的对象进行添加属性或者修改,如果直接通过如下直接赋值的方式是不会生效的。

export default {
  data () {
    return {
      persons: [
        {id: 1, name: "张三", age: 18},
        {id: 2, name: "李四", age: 15}
      ]
    }
  },
  methods: {
    changeObj(){
      this.persons[0] = {id: 1, name: "赵六", age: 88}  // 直接赋值不会生效
    }
  }
}

是因为一般在data中的属性或对象都会有各自对应的getter和setter,直接添加是没有这两个对应方法,导致不会去重新渲染模板,但是数据已经被修改的情况。通过使用Vue.set()可以解决新增属性或者修改属性达到动态修改渲染视图。

changeObj(){
  // 为某个对象添加属性;但是有局限性,只能给data中某个对象去追加属性,并不能直接往data身上直接追加
  this.$set(student, "gender", "male")

  // 修改数组的第一个元素
  this.$set(this.persons, 0, {id: 1, name: "赵六", age: 88})
}

※:也可以通过调用一些被vue包裹的api进行操作也会进行动态的渲染,例如数组的api,也可以被vue侦听到重新渲染模板

push()、pop()、shift()、unshift()、splice()、sort()、reverse()

3. 过滤器

通过一个 | 代表过滤器,类似Linux的管道操作,可以嵌套多个过滤器。

<p>{{ keywords | changeWord("yyyy") }}</p>   有参过滤器
<p>{{ keywords | changeMsg }}</p>            无参过滤器
<p>{{ keywords | changeMsg | changeWord("yyyy") }}</p>  嵌套过滤器
<script>
export default {
  filters:{
    changeWord(value, str){
      return value +  str
    },
    changeMsg (value){
      return value 
    }
  }
}
</script>

上面定义的是局部过滤器,组件和组件之间不能共用,下面定义全局过滤器。

Vue.filter("changeMsg",function (value){
  return value.subString(1)
})

4. 收集表单参数

通过 v-model 接收参数,只会接收到 input 类型的 value 值。当遇见CheckBox时会比较特殊。

乒乓球:<input type="checkbox" value="pingPang" v-model="hobby">
羽毛: <input type="checkbox" value="badminton" v-model="hobby">
<script>
export default {
  data(){
    return {
      hobby: [],   // 空数组接收CheckBox,接收到为各个value组成的数组
      hobby: ""    // 永远接收到true/fasle
    }
  }
}
</script>

还可以设置一些v-model接收的相关信息

v-model.lazy    // 代表懒加载,失去焦点时,才会将值同步过去
v-model.number  // 只接受数字类型
v-model.trim    // 自动去除空格

5. 一些指令

<p v-cloak>{{name}}</p>     // 在渲染前不会展示
<p v-once>{{age}}</p>       // 只会参与一次计算
<p v-pre>XXX</p>            // 不会解析内容

6. vue的生命周期(启动大致流程)

启动流程:
1 首先初始化Vue相关的事件、以及生命周期相关。
2 执行BeforeCreate钩子函数,此时还无法访问vm中的data、methods。
3 初始化数据监测、数据代理。
4 执行created钩子函数可以访问vm中的data、methods。
5 判断是否有配置el配置项,如果没有在vm.$mount(el)时候再执行。
6 判断是否有配置template配置项,如果没有则编译el的外部HTML作为模板,生成虚拟dom;如果有通过render函数解析模板。
7 执行beforeMount钩子函数,此时页面还未经过编译,所有对dom的操作都不会生效。
8 将虚拟dom 替换 真实dom,创建vm.$set 并替换掉 el。
9 执行mounted钩子函数,页面呈现经过vue编译的dom, 对dom的操作均奏效, 一般再次进行开启定时器,订阅消息,绑定自定义事件  初始化过程结束。

更新流程:
首先会执行 beforeUpdate钩子函数,此时数据是新的,页面是旧的。
然后根据新数据生成新的虚拟dom。
最后执行 updated 钩子函数,此时数据是新的,页面也是新的; PS:尽量不要在这里更改组件的状态有可能会导致无限循环。

销毁流程
首先会执行 beforeDestroy 钩子函数, 一般在此关闭定时器,取消消息订阅等工作  dom还可以用。
然后移除所有的组件以及所有的监视。
最后执行 destroyed 钩子函数。

当vm调用$destroy的时候就会触发销毁流程,调用该方法会清除vm实例,并清除它与其他实例的链接,解绑所有命令,只是会将自定义事件解除。
在销毁hook函数中放更新数据的操作,不会触发updated和beforeUpdate钩子的。

7. 组件相关

通过 Vue.extend 创建子组件

// 传入的参数和 new Vue的时候相似,不需要传$el这个属性
const newA = Vue.extend({
  data () {
    return {
      name: "sonComponent"
    }
  }
})

使用组件时,如果是单文件组件需要先引入。

<template>
  // 相当于一个标签进行使用,组件内部可以嵌套
  <top-bar></top-bar>
</template>
<script>
import topBar from './topBar'

export default {
  // 局部注册
  components: {
    // 别名: 实际组件名称
    topBar: topBar
  }
}
</script>

※:每个组件中的 this 都是指向当前组件对象。

注册全局组件:

Vue.component('hello', {})  // 名称,传递的对象和new Vue大致相同

组件的本质:

直接输出组件,会发现其本质就是一个构造函数 VueComponent,由 vue.extend 方法生成的。

ƒ VueComponent (options) {
    this._init(options);
}

※:vm 和 vc 有如下关系,这样是为了让 vc 也能使用 vm 的东西。让Vue原型对象作为兜底。

VueComponent.protoType.__proto__ === Vue.protoType  

8. ref 属性:可以通过ref 绑定一个dom对象,相当于 id 属性的替代品。

<p ref="tar">我是个标签</p>

<script>
    // 可以通过 this.$refs 拿到具体的dom,无需自己再手动操作dom
    console.log(this.$refs.tar)
</script>

9. props 属性:用于向组件传递参数,并规范接收参数的格式等属性。可以在子组件的 $attrs 查看到父组件传递但是并未声明接收的属性;如果接收了就不会出现在 $attrs 中。

向组件传递参数

<top-bar peach="桃子" pear="梨"></top-bar>

<!-- 加上冒号 通过绑定的形式进行传值  这样可以解决每次都是字符串的问题   -->
<top-bar peach="桃子" :pear="1"></top-bar>

接收参数

export default {
  // 方式一: 只写变量名称
  props: ['peach', 'pear']

  // 方式二: 指定类型接收,类型不匹配也能显示出来,但是会报错
  props: {
    'peach': String,
    'pear': Number
  }

  // 方式三: 指定每个字段的类型
  props: {
    'pear': {
      required: false,  // 指定是否必填
      type: String,     // 指定类型
      default: 'sdsd'   // 指定默认值
    }
  }
}

tips:props是只读的不能修改,如果需要修改需要在data中进行备份;当和自身的data中变量名称冲突时,props的优先级更高

10. 混入(mixIn)

所谓混入,就是将两个组件通用的逻辑抽离成一个单独的文件。

混入文件:

export default {
  mounted () {
    console.log("挂载")
  },
  methods: {
    makeNoise(){
      console.log("makeNoise")
    }
  }
}

局部混入:

import mix from '../public_minins'   // 引入混入文件

export default {
  // 如果方法或属性冲突了,会以当前实例的为主;如果生命周期钩子冲突会都执行。
  mixins: [mix]    // 可以混入多个js
}

全局混入:在 main.js 中进行配置

import mix from './public_minins'

Vue.mixin(mix)

11. 插件

插件的本质是个对象,但是必须要有一个install 方法,这个方法Vue会来调用。

定义插件:

export default {
  install(Vue, option){
    // 可以接收两个参数,第一个是Vue对象,第二个是注册时传入的参数
  }
}

注册插件:

import tip from './public_minins'

Vue.use(tip, '你的名字', '天气之子')

12. 事件总线

用于组件之间信息的传递,其实Vue中没有事件总线,只不过是向 Vue.prototype 身上定义了一个组件属性,这样可以让所有的 vm 和 vc 都可以使用,通过这个这个组件进行消息的绑定和触发,以此达到传递消息的目的。一般多用于兄弟组件之间。

定义事件总线:一般在beforeCreated中定义

new Vue({
  ...
  
  beforeCreate () {
    Vue.prototype.messageBus = this  // 创建一个事件总线 
  }
})

在A组件中注册事件

<script>
export default {
  name: 'A',
  mounted () {
    // 为总线绑定触发事件
    this.messageBus.$on("sendMessage", function (obj){
      console.log(obj)
    })
  },
  beforeDestroy () {
    // 在组件销毁时最好解绑事件
    this.messageBus.$off("sendMessage")
  }
}
</script>

在B组件触发事件

<script>
export default {
  name: 'Item',
  props: ["obj"],
  methods:{
    clickMe(){
      this.messageBus.$emit("sendMessage", this.obj)
    }
  }
}
</script>

13. 动画和过渡

动画和过渡都需要 <transition> 标签对HTML元素进行包裹。通过v-show控制元素是否展示。

<template>
    <!-- 定义name以后vue会根据name名称寻找css,appear接收布尔值用于控制进入页面是否触发动画 -->
    <transition name="me" :appear="true">
        <div v-show="isShow" style="width: 100px; height: 100px">AAAA</div>
    </transition-group>
</template>

动画css的定义:需要定义好@keyframe,以及按照vue规则定义好的css。vue的类名规则是:name(transition标签中定义的name,如果没有定义默认是 v) - 动作(enter / leave) - active。

<style scoped>
  /*动画离开时激活的效果 */
  .me-leave-active{
    animation: mymove 1s reverse;
  }

  /*动画进入时激活的效果 */
  .me-enter-active{
    animation: mymove 1s;
  }

  @keyframes mymove {
    from{
      transform: translateX(-100px);
    }
    to{
      transform: translateX(100px);
    }
  }
</style>

过渡效果css的定义:这里也是需要和name属性一起使用,不过有个技巧是,过渡开始起点就是过渡结束的终点,过渡开始终点就是过渡结束起点。

<style scoped>
  /*过渡开始起点,已经结束的终点 */
  .me-enter, .me-leave-to{
    transform: translateX(-100%);
  }

  /*过渡进入、离开执行 */
  .me-enter-active, .me-leave-active{
    transition: 0.5s linear;
  }

  /*过渡开始终点,结束起点*/
  .me-enter-to, .me-leave{
    transform: translateX(100%);
  }
</style>

※:transition 标签只能对一个元素进行控制,多个需要用 transition-group 标签,并为每个元素配置 key属性。

14. nextTick

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。有点类似 setTImeOut。

this.$nextTick(function (){})

15. 插槽(slot)

为了展示在子组件标签中的HTML,需要在子组件中定义slot标签用于标识展示的位置;类似于给子组件传了一段HTML过去;好比在子组件中挖坑,父组件调用时传递。可以在子组件的 $slots 上查看到插槽信息。如果父组件传递但是子组件没有展示也不会丢失,还会在 $slots 中出现。

默认插槽:如果没有传slot对应的内容会展示默认文字。

父组件:
    <span>卓哥哥</span>

子组件:
    <template>
      <div><slot>slot标签中可以显示文字是默认内容</slot></div>
    </template>

具名插槽:在slot标签上添加name属性。父组件中通过slot属性进行指定,如果父组件中传递的是template标签还有第二种写法。

父组件:
    <template>
      <div><span slot="head">卓哥哥</span></div>
    </template>

子组件:
    <slot name="head">slot标签中可以显示文字是默认内容</slot>

template标签传递:

父组件:
    <template>
      <div><template v-slot:head></template></div>
    </template>

子组件:
    <slot name="head">slot标签中可以显示文字是默认内容</slot>

作用域插槽:子组件可以将自身的数据传入slot中,父组件引用时 通过slot-scope进行获取,还可以在这里进行结构解析。

父组件:
   <div slot="head" slot-scope="obj">
     <span v-for="item in obj.games" :key="item">{{item}}</span>
   </div>

子组件:
    <slot name="head" :games ="games" >slot标签中可以显示文字是默认内容</slot>

16. axios 和 vue-resource

axios 和 vue-resource 都是类型Ajax的异步请求工具。一般推荐使用axios,vue-resourcce年久失修。 两者返回的都是promise的结构。

17. 路由

在vue中使用路由控制展示的组件,文件一般定义在 router/index.js。在创建vue实例的时候需要传递进去。

import Router from 'vue-router'   // 引入路由

Vue.use(Router)    // 使用路由

export default new Router({
  mode: 'history', // 默认是hash模式(url代#) history(不带#)
  routes: [        // route中定义多组路由信息
    {
      path: '/app',   // 路径, 一级路由需要加斜杠
      name: 'App',    // 路由名称
      component: App,   // 展示的组件
      children:[        // 定义二级路由
        {
          path: 'grandson',   // 子级都不需要斜杠
          name: 'grandson',
          component: grandson,
        },{...}
      ]
    },{...}
  ]
})

添加 vue-router 以后就会多了$router 和 $route 属性,每个组件都会有属于自己的 $route 属性,所有组件的 $router 都是相同的,也就是说全局只会有一个$router属性。

在vue中很少使用<a>标签,转而更多的会用 <router-link> 标签,经过vue编译后的 <router-link> 也会转变成 <a> 标签。

<!--to: 指定跳转的组件路由
    active-class: 指定激活时的样式
    replace: 请求路由会替换当前记录
 -->
<router-link to="/group1">group1</router-link>

通过 router-link 标签给跳转组件传递参数:

(1) 通过 $route.query 参数

<!-- 这样传递参数会放到$route.query中,${} 进行参数值的获取  简写形式-->
<router-link to="/group1/grandson?msg=${item.id}">component</router-link>

<!-- to属性传递一个对象的格式 标准形式1  -->
<router-link :to="{
  path: '/group1/grandson',   // 指定跳转路由
  query:{ msg: 'QQPP' }// 指定query的参数
}">component</router-link>

<!-- 通过名称指定路由 标准形式2  -->
<router-link :to="{
  name: 'component', 
  query:{ msg: 'QQPP' }
}">component</router-link>

(2) 通过$route.param接收

首先需要在路由中定义好每个占位的变量。

{
  path: 'grandson/:msg/:title',   // 通过 冒号+变量名的格式
  component: grandson
}

在传递的时候直接传递

<!-- 通过斜杠直接往后拼接  写法一-->
<router-link to="/group1/grandson/消息/标题">component</router-link>

<!--写法二  -->
<router-link :to="{
  path: '/group1/grandson',   
  params:{ msg: '消息', title: '标题' }
}">component</router-link>

通过props进行参数传递

// 传递死数据
{
  path: 'grandson',
  component: grandson,
  props: {msg: "消息标题"}     // 将值以props属性形式传递给目标组件
}

// 如果值为真 将路由组件收到的 params 参数以 props 形式传递给组件
{
  path: 'grandson',
  component: grandson,
  props: true
}

// 函数的返回值作为 props 形式传递给组件
{
  path: 'grandson',
  component: grandson,
  props: function ($route){  //  这里更简单的写法是结构解析
    return {msg: $route.params.msg}
  }
}

缓存组件的内容:使用 <keep-alive> 标签进行缓存组件,通过include可以指定缓存哪些组件,值是组件名称;需要注意 <keep-alive> 需要给 <router-view> 使用。

<router-link to="/group1/grandson">component1</router-link>
<router-link to="/group1/grandson2">component2</router-link>
<p>
  <keep-alive :include="['grandson2',]">
    <router-view/> 
  </keep-alive>
</p>

使用 router 后会新增两个钩子函数,需要注意组件需要被 <keep-alive> 标签进行包裹。

activated () {        // 组件激活时触发的hook函数
  console.log("激活")
},

deactivated () {      // 组件失活时触发的hook函数
  console.log("失活")
}

前置路由守卫

/* to: 前往的路由
  from: 起始的路由
  next: 放行函数
*/
router.beforeEach((to, from, next) => {
  if(to.path.indexOf('grand') === -1){
    next()  // 放行,如果不执行next就代表 被阻塞了
  }
})

后置路由守卫

/* to: 前往的路由
   from: 起始的路由
*/
router.afterEach((to, from) => {})

路由自定义信息

{
  path: '/App',
  name: 'App',
  component: App
  meta: {}   // 这里可以自定义一些数据
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值