# 8.容易遗忘点汇总

1.provide/inject

provide进去的值不是响应式的,要获得响应式效果要通过Object.definePropertyprovide的值可以是一个Object或者返回Objectfunction

// 根组件provide
new Vue({
  el: '#app',
  data: { inputName: 'xiaoming' },
  provide() {
    const data = {}
    Object.defineProperty(data, 'value', {
      get: () => this.inputName, // 'xiaoming'
      enumberable: true,
    })
    return { name: this.inputName, data }
  },
})

// 子组件inject
Vue.component('model-comp', {
  inject: ['name', 'data'],
  mounted() {
    console.log(this.data)
  },
})
  1. 在含有router-view的组件中可以写以下方法来做出相应动作
watch:{
  '$route'(to,from){
    console.log('to:',to)
    console.log('from:',from)
  }
}

3.router-link本身不能添加类,所以要加一层div

4.命名视图

命名视图对应的路由routes中要用components

children: [
  {
    path: ':username',
    components: {
      default: Dynamic,
      'dynamic-one': DynamicOne,
    },
  },
]

5.this.$route.params 是路由有冒号开头的部分,如下返回的是{id:xxxx}

{
  path:'/recommend',
  component:Recommend,
  children:[
    {
      path:':id',
      component:Disc
    }
  ]
}

6.this.$route.query 是路由中?后面的部分

  1. routerhistory的模式

routerhistory的模式下可以设置base属性,添加后会在每个路由前面添加这个base路径。base路径的前后都要有斜杠 /

base:'/base/',
mode:'history'

8.webpack的NamedModulePlugin(dev)HashedModuleIdsPlugin(prod)

这两个 plugin 让 webpack 不再使用数字给我们的模块进行命名,这样每个模块都会有一个独有的名字,也就不会出现增删模块导致模块 id 变化引起最终的 hash 变化了。

  1. 通过new创建的实例
  • propsData只用于new创建的实例中,通过new创建的实例propsdata的写法如下,具体例子见这里(opens new window)
const instance = new NotificationConstructor({
  propsData: {
    ...rest,
  },
  data: {
    autoClose: autoClose === undefined ? true : autoClose,
  },
}).$mount()
  • 通过new建立的组件dataobject,其它情况下定义的组件data都是一个functionreturn object

  • 通过new定义新组件的时候可以指定parent,跟其它选项一样并列

  1. computed 的setter

如果setter不改变getter中的依赖,则 computed 出来的值不会改变。

computed 里面 setter 方法的调用时机:例如有 computed 属性num,在其他地方通过this.num = 'xx'num赋值的时候才会调用set方法

11.作用域插槽

  • (v2.5.0+) 只有在父组件引用子组件的标签上写了slot-scope,子组件里面的$scopedSlots属性对象才有值,且只要该标签写了slot-scope,它将不会出现在$slots对象中,只出现在$scopedSlots对象中。即一个插槽不会同时出现在$slots/$scopedSlots中。

  • v-slot(v2.6+)

render函数中静态插槽和作用域插槽都推荐通过$scopedSlots使用,调用方法如下: this.$scopedSlots.default()/this.$scopedSlots.header()

如需对外传递数据,则在括号里添加对象this.$scopedSlots.header({msg:99}),外部可通过v-slot:header="{msg}"访问

组件只有一个默认插槽时,可直接在组件引用标签上使用v-slot获取组件对外提供的值,如果有多个插槽,默认插槽及具名插槽对外提供的值都必须通过template语法来获得,否则会报错To avoid scope ambiguity, the default slot should also use <template> syntax when there are other named slots.

// 错误用法,会报上面提到的错误
<test v-slot="{ x, y }">x,y---{{x}},{{y}}
  <template v-slot:one>custom slot one content</template>
</test>

// 多个插槽的时候,正确用法
<test>
  <template v-slot="{x,y}">x,y---{{x}},{{y}}</template>
  <template v-slot:one>custom slot one content</template>
</test>

// 单个默认插槽可写在组件标签上或者使用template语法
<test v-slot="{ x, y }">
  x,y---{{x}},{{y}}
</test>
  1. transition
  • transition里面只能包含一个根元素,所以不能用 v-show(还停留在 dom 结构里),只能只 v-if、v-else 进行多个组件的切换。
  • 自定义过渡类名对transitiontransition-group都生效

  • transitiontransition-group或其它封装的过渡组件里面包裹的元素都只能是原生元素标签,否则不生效,如下则不生效。

<fade-animation>
  <gallary :list="gallaryImgs" ref="gallary"></gallary>
</fade-animation>
  • 初始渲染的过渡可以通过设置appear相关class实现
  1. 修改开发环境使用的 vue 版本
  1. props自定义验证validator
props:{
  propsOne:{
    validator(val){
      return typeof val === 'boolean'
    }
  }
}

15.Vue.extend

Vue.extend或者在options里面写extends可以继承组件,使用场景:某个组件功能比较完善了需要拓展新的功能,但又不想改动它,新组件直接extends,具体例子见这里(opens new window)

16.Vue.use(plugin)的暴露方式

具体例子见这里(opens new window)

import Notification from './notification'
import notify from './notify'

// Notification.install = (Vue) => {
//   Vue.component(Notification.name,Notification)
//   Vue.prototype.$notify = notify
// }
// export default Notification
export default Vue => {
  Vue.component(Notification.name, Notification)
  Vue.prototype.$notify = notify
}
  1. 生产环境的productionSourceMap应该设置成false,防止别人调试

  2. key

key管理可复用的元素,v-if会使组件重走生命周期,v-show则不会让组件重走生命周期,通过component进行动态组件切换会重新走生命周期。

  1. Function形式的props

props如果传的是FunctionFunctionreturn 值的话,可以在父组件直接改变子组件的data,如果不返回值,子组件内部的操作可以改变父组件的data等。React同理

20.异步更新队列

为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用 Vue.nextTick(callback)

  1. this.$forceUpdate()会迫使 Vue 实例重新渲染。

  2. this.$set(obj,obj.name,val)Vue.set(obj,key,val)

23.使用keep-alive标签的情况:component /router-view,改变里面的数据用activeddeactived这两个钩子

24.views文件夹下面的文件推荐使用kebab-case命名,因为路由也是连字符

25.vue-router通过addRoutes添加的路由刷新后报404解决方案:

不在默认路由里添加 path:'/404' 的路由,对于无权限页面,可以做以下配置,addRoutes菜单权限参考这里(opens new window)

{
  path:'*',
  component:{
    render:h=>h('h1',{},'Not Found')
  }
}
  1. 以下官网的提示 render 指的是入口函数的 render,对于.vue 文件,同时包含templaterender,会渲染 template 而不是render