0Vefl6r61uQ.jpg

路由器参数解耦

我相信这是大多数人处理组件中路由器参数的方式

  1. export default {
  2. methods: {
  3. getRouteParamsId() {
  4. return this.$route.params.id
  5. }
  6. }
  7. }

在组件内部使用 $route 会对某个URL产生强耦合,这限制了组件的灵活性

router.js

  1. const router = new VueRouter({
  2. routes: [{
  3. path: '/:id',
  4. component: Component,
  5. props: true
  6. }]
  7. })
  8. //或者
  9. const router = new VueRouter({
  10. routes: [{
  11. path: '/:id',
  12. component: Component,
  13. props: router => ({ id: route.query.id })
  14. }]
  15. })
  1. export default {
  2. props: ['id'],
  3. methods: {
  4. getParamsId() {
  5. return this.id
  6. }
  7. }
  8. }


v-for和v-if的联合用法

前端时间面试的时候, 有个面试官问我, v-for和v-if哪个优先级高, 是v-for的优先较高
业务中尽量不要出现v-if和v-for的联合用法

优化方案:

  1. // 计算属性
  2. computed: {
  3. filterList: function () {
  4. return this.showData.filter(function (data) {
  5. return data.isShow
  6. })
  7. }
  8. // DOM
  9. <ul>
  10. <li v-for="item in filterList" :key="item.id">
  11. {{ item.name }}
  12. </li>
  13. </ul>

避免空class

  1. <!-- 不建议 --><div :class="isBold ? 'bold' : ''"></div><!-- <div class> -->
  2. <!-- 推荐写法 --><divclass ="isBold?'bold': null"></div> <!-- <div > -->

内容loading加载

设想一个场景 如果我们需要在数据渲染到页面的之前让页面 loadingmounted 之后停止 loadingbeforeUpdata 时开始 loadingupdatad 之后停止 loading
最简单的方法就是改写组件的生命周期函数,使其在 mounted/beforeUpdata /updatad 时通知父组件显示或者隐藏 loading。

缺点

因为侵入了自组件的逻辑,增加的逻辑也和组件本身的功能好不关联。最好的办法就是使用 v-on="hook:xxx" 的方式:

  1. <v-chart
  2. @hook:mounted="loading = false"
  3. @hook:beforeUpdated="loading = true"
  4. @hook:updated="loading = false"
  5. :data="data"
  6. />

sync语法糖

我们知道父传子,单向传递的,props,在一切特殊场景下,我们需要子组件修改父组件的值

image.png

object.freeze优化性能

  1. export default {
  2. data: () => ({
  3. users: {}
  4. }),
  5. async created() {
  6. const users = await axios.get("/api/users");
  7. this.users = Object.freeze(users);
  8. }
  9. };

computed和watch使用场景的区分

计算属性computed:

  • 支持缓存,只有依赖数据发生改变,才会重新进行计算
  • 不支持异步,当computed内有异步操作时无效,无法监听数据的变化
  • computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值
  • 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed
  • 如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。

    侦听属性watch:

  • 不支持缓存,数据变,直接会触发相应的操作;

  • watch支持异步;
  • 监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
  • 当一个属性发生变化时,需要执行对应的操作;一对多;
  • 监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数:

immediate:组件加载立即触发回调函数执行
deep: deep的意思就是深入观察,监听器会一层层的往下遍历,给对象的所有属性都加上这个监听器,但是这样性能开销就会非常大了,任何修改obj里面任何一个属性都会触发这个监听器里的 handler
image.png

vue如何监听对象或者数组某个属性的变化

  1. this.$set(this.arr, 0, "OBKoro1"); // 改变数组
  2. this.$set(this.obj, "c", "OBKoro1"); // 改变对象

vue如何获取dom

先给标签设置一个ref值,再通过this.$refs.domName获取

  1. <div ref="test"></div>
  2. const dom = this.$refs.test

on监听多个方法

  1. <input type="text" v-on="{ input:onInput,focus:onFocus,blur:onBlur, }">

assets和static的静态文件处理

  1. 这两个都是用来存放项目中所使用的静态资源文件。
  2. 两者的区别:
  3. assets中的文件在运行npm run build的时候会打包,简单来说就是会被压缩体积,代码格式化之类的。打包之后也会放到static中。
  4. static中的文件则不会被打包。

将图片等未处理的文件放在assets中,打包减少体积。而对于第三方引入的一些资源文件如iconfont.css等可以放在static中,因为这些文件已经经过处理了。

关于静态资源的优化,尤其是图片,这里有几个建议

  • 小图标使用 SVG 或者字体图标
  • 通过 base64webp 的方式加载小型图片
  • 能通过cdn加速的大图尽量用cdn
  • 大部分框架都带有懒加载的图片,不要嫌麻烦,多花点时间使用它

    ajax请求代码应该写在组件的methods中还是vuex的actions中

    如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。
    如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用。


    在v-model上怎么用Vuex中state的值

  1. <input v-model="message">
  2. // ...
  3. computed: {
  4. message: {
  5. get () {
  6. return this.$store.state.message
  7. },
  8. set (value) {
  9. this.$store.commit('updateMessage', value)
  10. }
  11. }
  12. }

mutation和action有什么区别

  • action 提交的是 mutation,而不是直接变更状态。mutation可以直接变更状态
  • action 可以包含任意异步操作。mutation只能是同步操作
  • 提交方式:

    1. action 是用this.store.dispatch('ACTION_NAME',data)来提交。
    2. mutation是用this.$store.commit('SET_NUMBER',10)来提交
  • 接收参数不同,mutation第一个参数是state,而action第一个参数是context,其包含了

组件中重复使用mutation

  1. import { mapMutations } from 'vuex'
  2. methods:{
  3. ...mapMutations({
  4. setNumber:'SET_NUMBER',
  5. })
  6. }

调用方式
然后调用this.setNumber(10)相当调用this.$store.commit(‘SET_NUMBER’,10)


vue-router路由配置

主意其他错误错误路径进入的跳转

  1. {path: '*', reditct: '/home'}

路由按需加载

  1. {
  2. path:'/',
  3. name:'home',
  4. components:resolve=>require(['@/components/home'],resolve)
  5. }
  6. webpack> 2.4
  7. {
  8. path:'/',
  9. name:'home',
  10. components:()=>import('@/components/home')
  11. }

import()方法是由es6提出的,动态加载返回一个Promise对象,then方法的参数是加载到的模块。类似于Node.js的require方法,主要import()方法是异步加载的。

vue路由传参

使用query方法传入的参数使用this.$route.query接受, 内部传参this.$router.push(‘product?id =’ + id)

使用params方式传入的参数使用this.$route.params接受, /product/:id

router和route的区别

route为当前router跳转对象, 里面可以获取name、path、query、params等

router为VueRouter实例,想要导航到不同URL,则使用router.push方法

Vue里面router-link在电脑上有用,在安卓上没反应怎么解决

Vue路由在Android机上有问题,babel问题,安装babel polypill插件解决


Vue2中注册在router-link上事件无效解决方法

使用@click.native。原因:router-link会阻止click事件,.native指直接监听一个原生事件


RouterLink在IE和Firefox中不起作用(路由不跳转)的问题

  • 只用a标签,不使用button标签
  • 使用button标签和Router.navigate方法