vue使用总结

栏目: JavaScript · 发布时间: 6年前

内容简介:从以下几个方面整理:以上 main.js 中也可以通过 Vue.use 注册,其实实质还是调用 Vue.Component,对应的 use 的需要有一个 install 函数,使用 Vue.use 将触发 install 执行,然后在 install 中执行 Vue.component 操作。a.vue 和 b.vue,引用 bus.js ,Bus 为同一个实例,并不会重复创建,bus.js 就相当于一个调度中心,可以无数个组件,都和它建立链接,发布事件,然后 bus 将发布到给每一个建立链接的组件。

使用心得

从以下几个方面整理:

  • vue 用法
  • vue-router 用法
  • webpack 打包
  • 遇到的坑

Vue 用法

  1. 通常写的 .vue 文件,实则是在写 vue 的配置文件,最终将执行 new Vue() 的操作,传入这些配置。
new Vue({
  data(){
    return {
      name:'xx'
    }
  }
})

// 常编写的.vue文件
export default {
  data(){
    return {
      name:'xx'
    }
  }
}
  1. 常用组件可以在全局注册。
  • 组件代码,TestComp.vue
<template>
    <div>
    test component
  </div>
</template>
<script>
export default {}
</script>
  • 注册组件,Vue.component 注册
// main.js
import Vue from 'vue';
import TestComp from './TestComp.vue'
Vue.component('test-comp',TestComp);

以上 main.js 中也可以通过 Vue.use 注册,其实实质还是调用 Vue.Component,对应的 use 的需要有一个 install 函数,使用 Vue.use 将触发 install 执行,然后在 install 中执行 Vue.component 操作。

// my-components.js
import TestComp from './TestComp.vue'
export default {
    install(Vue){
    Vue.component('test-comp',TestComp)
    // 这里还可以有多个注册 vue.component vue.directive, vue.filter 等
  }
}
// main.js
import Vue from 'vue';
import MyComponents from './my-components.js';
Vue.use(MyComponents)
  1. 用的比较多的指令,过滤器,mixin,可以在全局配置
/* 1、 注册指令 */
Vue.directive('')

/* 2、注册过滤器 */
Vue.filter('filterName',(val,...args)=>{
  console.log(args); 
  return val;
})
// 过滤器使用 {{ 'abc' | filterName(1,2,3) }}
// value = 'abc' args 为 [1,2,3]

/* 3、全局 mixin (不建议) */
Vue.mixin({
  mounted(){
    console.log('每个组件中都将执行这里')
  }
})
  1. keep-alive 的使用,可以缓存组件,可以通过 exclude 排除不需缓存的组件,include 包含需要缓存的,max 定义最大缓存的组件数。exclude,include 传入一个数组,元素对应组件的 name 属性,max 传入数字。
<keep-alive :incude="['home','list']" :max="3">
  <router-view></router-view>
</keep-alive>
  1. 在页面跳转时,新打开的页面滚动条可能缓存了滚动条位置,在中间的位置,进入页面或者在路由钩子的 afterEach 中执行 window.scroll(0,0) 重置到顶部。
  2. 非直接父子组件之间的通信,使用一个空 vue 对象实现通信。
// Bus.js
import Vue from 'vue'
export const Bus = new Vue()

// a.vue
import Bus from './bus.js'
Bus.$emit('event_add_cart',1)

// b.vue
import Bus from './bus.js'
Bus.$on('event_add_cart',(num)=>{
  this.cartNum += num
})

a.vue 和 b.vue,引用 bus.js ,Bus 为同一个实例,并不会重复创建,bus.js 就相当于一个调度中心,可以无数个组件,都和它建立链接,发布事件,然后 bus 将发布到给每一个建立链接的组件。

  1. computed 只有在依赖的 data 里面的值改变时,才会改变,优于直接在模板里执行表达式和方法,因为模板中的方法和模板,在每次 Vue 刷新视图时,都将重新执行一遍。
  2. data 需要是一个函数返回一个对象,如果直接赋值一个对象时,做不到隔离同一个组件的数据效果,都将公用同一份数据。
  3. 在 vue 组件销毁(beforeDestroy)前,清理定时器和 DOM 事件绑定。
  4. 在循环中使用 key,提升渲染性能,key 尽量不用数组下标,有 key 则 diff 算法就比较 key 值,最大程度上使用原组件,而不是销毁原来的组件后重建。
  5. v-for 可以和 v-if 同时使用,先循环再判断,所以可以有选择的渲染数组中的元素,而 angular 中是不支持同一个标签上同时存在 for 和 if 指令的。可能 eslint 会提示报错不建议混合使用,eslint 建议使用改变数组源数据的方式来实现,可以在 computed 中使用数组的 filter 过滤掉不想要的数据。
  6. 模板中 template 的使用,当几个同级的元素,需要依赖同一个指令时,又不想添加额外的标签将这些元素包裹时,可以使用 template,template 将不会渲染。在 template 使用 v-for 时,key 值需要添加在子元素上。
<template>
    <div>
    <template v-for="(item,index) in [1,2,3]">
      <div :key="index">
        {{item}}
      </div>
    </template>
        <template v-if="2>1">
            <div>
        2大于1
      </div>
            <div>
        2>1
      </div>    
        </template>
  </div>
</template>
  1. 在 data 初始化时,对象类型的数据类型,如果不给初始化,单独改变值时,页面是不会响应该值的变化的。
<template>
    <div>
    {{info.name}}
    {{info.age}}
    <div v-for="(item,index) in arr"
         :key="index">{{item}}</div>
  </div>
</template>
<script>
 export default {
   data(){
     return {
       info:{ age:1 },
       arr:[],
         }
   },
   mounted(){
     this.info.name = 'xx'; // 并不能触发页面更新
     this.info.age = 2; // 这样子可以触发页面更新
     this.info = {name:'xx'}; // 这样子可以触发页面更新
     
     // 数组同理
     this.arr[0] = 1; // 并不能触发页面更新
     this.arr = [1]; // 这样子可以触发页面更新
   }
 }
</script>

因为 Vue 在初始化时需要对 data 进行使用 defineProperty 进行 set 和 get 的劫持,如果对象中的值为空,那就不会存在相应的 set 和 get,所以两者方式,一个给对象里面设置初值,二个将对象改为一个新对象,而不是直接在上面添加属性和值。

基于以上,还有一个使用技巧,则是,一些表单如果依赖后台返回的一些数据初始化选择列表等,那么可以在赋值前,先在返回的数组中,加上一个属性,例如 isChecked,然后再赋值给 data

<template>
    <div>
   <template v-for="(item,index) in checkboxs">
      <input type="checkbox"
             v-model="item.isChecked"
             :key="index">
    </template>
  </div>
</template>
<script>
export default {
    data(){
    return {
      checkboxs:[]
        }
  },
  methods:{
    getData(){
      // 请求过程略 
      let data = [{name:'zs',name:'ls'}] // 原请求返回数据
      this.checkboxs = data.forEach(item=>Object.assign(item,{isChecked:false}))
    }
    }
}
</script>
  1. 开发组件时,可以用 slot 占位,内容在使用组件的地方填充,使组件更加灵活。
  2. 在开发管理后台时,可以将通用的数据和方法,写在 mixin 里面,然后在页面中注入,如通用表格的页码配置数据,加载中状态值,还有获取上一页,下一页的方法。
  3. 在查看大图的场景中,点开大图,安卓物理键返回时,需要关闭大图,而不进行页面的跳转,则是可以在点开大图的时候,pushState 在 history 中添加一个路由,如果页面需要点击关闭的功能,则需要在点关闭按钮时,手动触发 history.go(-1) 一下;
  4. 如果在例如一个操作结果页(比如支付完成),然后又不能手动配置分享内容的时候,又需要分享的是购买的商品时,则可以通过 replaceState 方法改变路由,但是又不会触发页面刷新,再分享时,app或者浏览器则会自动抓取到替换后的地址分享出去了。
  5. 父组件可以通过 @hook:created @hook:mounted 等监听到子组件的生命周期。
  6. errorCaptured 捕获子孙组件的错误。
  7. slot 插槽的使用

    • 匿名插槽
    // child.vue
    <template>
        <header>
        <slot>all header</slot>
      </header>
    </template>
    
    // parent.vue
    <template>
        <child>
        <div>this is custom header</div>
      </child>
    </template>
> slot 中可以有默认值

- 具名插槽

```vue
// child.vue
<template>
    <header>
    <slot name="left">left</slot>
    <slot name="right">right</slot>
  </header>
</template>

// parent.vue
<template>
    <child>
    <div slot="left">custom left</div>
    <div slot="right">custom right</div>
    <div slot="right">custom right2</div>
  </child>
</template>
```

> 具名插槽可以有一个以上同样 name 的填充。注意组件中用 slot + name ,使用时用 slot=name ,这里容易搞混。

- 带值传递插槽,slot-scope,也就是子组件的值传递给父组件

```vue
// child.vue
<template>
  <header>
    <slot :user="userinfo"
          :address="address"></slot>
  </header>
</template>
<script>
export default {
  data() {
    return {
      userinfo: { name: 'haokur' },
      address: { city: 'guangzhou' },
    }
  },
}
</script>

// parent.vue
<template>
  <div>
    <Child>
      <template slot-scope="row">
        {{JSON.stringify(row)}} => {"user":{"name":"haokur"},"address":{"city":"guangzhou"}}
      </template>
    </Child>
  </div>
</template>
```

- 带值传递插槽的使用场景,在 element-ui 中使用的较多,当在非父组件中的循环时,而是向子组件传递值,子组件去遍历时,父组件中的插槽无法拿到遍历的当前值,需要子组件在遍历的时候,把值又给附加在 slot 上。

```js
// List.vue
<template>
  <ul class="table">
    <li class="row"
        v-for="(item,index) in dataList"
        :key="index">
      <slot :row="item">
        {{item}}
      </slot>
    </li>
  </ul>
</template>
<script>
export default {
  props: ['dataList'],
}
</script>

/// parent.vue
<template>
  <div>
    <TestList :dataList="[1,2,3,4,5,6]">
      <template slot-scope="scope">
        {{ scope.row * 2 }}
      </template>
    </TestList>
  </div>
</template>
```

> 于是就实现了,子组件反向又像父组件传递值
  1. v-once 进行渲染优化,v-once 只会初始化一次,之后页面数据发生变化,v-once 内的内容也不会发生变化。
<template>
  <div>
    <span v-once>{{dateNow}}</span>
    <span>{{dateNow}}</span>
  </div>
</template>
<script>
export default {
  data(){
    return {
      dateNow: Date.now()
      }
  },
  mounted(){
    setInterval(() => {
      this.dateNow = Date.now()
    }, 1000)
  }
}
</script>

测试可看到只有没有加 v-once 的时间在变。

  1. 关于在 created 还是在 mounted 生命钩子里发送数据请求。有些说法是放在 created 中会好一些,可以避免多渲染一次?其论据可能是数据如果加载得快,那么就不render默认初始值,而是直接拿到获取到的数据,然后render?先给出我的结论,created 和 mounted 中基本无差,两者的渲染次数是一致的。
<script>
export default {
  created(){
    this.name = 'hello';
    setTimeout(() => {
      this.name = 'haokur'
    }, 0)
  },
  mounted(){
    // this.name = 'xiao'
    //setTimeout(() => {
    //  this.name = 'haokur'
    //}, 0)
  },
  render(h){
    console.log('执行渲染',this.name)
    return h('div',{},this.name)
    }
}
</script>
以上测试可知, 执行渲染

将进行两次,也就是再快的数据返回,也是要进行两次 render 的。因为请求和setTimeout 一样都是异步的,所以它的执行结果是在事件队列中等着的,而 render 是当前执行栈中的同步方法,它是执行在事件队列中的方法之前的。

注释 created,放开mounted ,render 方法则会执行三遍。

但是 created 和 mounted 中直接赋值则是有差别的,因为 render 会发生在 mounted 之前一次。也就是初始化时,created =》render =》 mounted =》(若有更改,再次 render) =》 请求返回 =》 再次 render

所以最佳的处理方式是,同步更改数据的,放 created 中,这样一些初值在第一次渲染就能正确呈现,且比在 mounted 中少执行一遍 render ,异步更改的无所谓。

  1. is 的使用,在一些特定的结构中使用组件,如 ul 下的 li
// UserItem.js
<template>
    <li>this is useritem</li>
</template>

// container.js
<template>
    <ul>
    <li is="user-item"></li>
  </ul>
</template>
<script>
import UserItem from './UserItem.js'
export default {
    components:{
    'user-item':UserItem
  }
}
</script>

双向数据绑定的说法再圆一下

三大框架对比,有条理点理一下

vue 的 functional 属性

Proxy


以上所述就是小编给大家介绍的《vue使用总结》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

ANSI Common Lisp

ANSI Common Lisp

Paul Graham / Prentice Hall / 1995-11-12 / USD 116.40

For use as a core text supplement in any course covering common LISP such as Artificial Intelligence or Concepts of Programming Languages. Teaching students new and more powerful ways of thinking abo......一起来看看 《ANSI Common Lisp》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换