1,props

  1. // 数组:不建议使用
  2. props:[]
  3. // 对象
  4. props:{
  5. inpVal:{
  6. type:Number, //传入值限定类型
  7. // type 值可为String,Number,Boolean,Array,Object,Date,Function,Symbol
  8. // type 还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认
  9. required: true, //是否必传
  10. default:200, //默认值,对象或数组默认值必须从一个工厂函数获取如 default:()=>[]
  11. validator:(value) {
  12. // 这个值必须匹配下列字符串中的一个
  13. return ['success', 'warning', 'danger'].indexOf(value) !== -1
  14. }
  15. }
  16. }

2.$emit

  1. // 父组件
  2. <home @title="title">
  3. // 子组件
  4. this.$emit('title',[{title:'这是title'}])

3.vuex 状态管理器

state:定义存贮数据的仓库 ,可通过this.$store.state 或mapState访问
getter:获取 store 值,可认为是 store 的计算属性,可通过this.$store.getter 或
mapGetters访问
mutation:同步改变 store 值,为什么会设计成同步,因为mutation是直接改变 store 值,
vue 对操作进行了记录,如果是异步无法追踪改变.可通过mapMutations调用
action:异步调用函数执行mutation,进而改变 store 值,可通过 this.$dispatch或mapActions
访问
modules:模块,如果状态过多,可以拆分成模块,最后在入口通过…解构引入

4 attrs和listeners

  1. attrs场景:如果父传子有很多值,那么在子组件需要定义多个props解决:attrs 场景:如果父传子有很多值,那么在子组件需要定义多个 props 解决:attrs场景:如果父传子有很多值,那么在子组件需要定义多个props解决:attrs获取子传父中未在 props 定义的值 ```javascript // 父组件

// 子组件 mounted() { console.log(this.$attrs) //{title: “这是标题”, width: “80”, height: “80”, imgUrl: “imgUrl”} }, 相对应的如果子组件定义了 props,打印的值就是剔除定义的属性 props: { width: { type: String, default: ‘’ } }, mounted() { console.log(this.$attrs) //{title: “这是标题”, height: “80”, imgUrl: “imgUrl”} },

  1. _**listeners**_**场景**:子组件需要调用父组件的方法解决:父组件的方法可以通过_v__on_="listeners" 传入内部组件——在创建更高层次的组件时非常有用
  2. ```javascript
  3. // 父组件
  4. <home @change="change"/>
  5. // 子组件
  6. mounted() {
  7. console.log(this.$listeners) //即可拿到 change 事件
  8. }
  9. 如果是孙组件要访问父组件的属性和调用方法,直接一级一级传下去就可以
  10. inheritAttrs
  11. // 父组件
  12. <home title="这是标题" width="80" height="80" imgUrl="imgUrl"/>
  13. // 子组件
  14. mounted() {
  15. console.log(this.$attrs) //{title: "这是标题", width: "80", height: "80", imgUrl: "imgUrl"}
  16. },

inheritAttrs默认值为true,true的意思是将父组件中除了props外的属性添加到子组件的根节点上(说明,即使设置为true,子组件仍然可以通过$attr获取到props意外的属性)
将inheritAttrs:false后,属性就不会显示在根节点上了

5.provide和inject

  1. //父组件:
  2. provide: { //provide 是一个对象,提供一个属性或方法
  3. foo: '这是 foo',
  4. fooMethod:()=>{
  5. console.log('父组件 fooMethod 被调用')
  6. }
  7. },
  8. // 子或者孙子组件
  9. inject: ['foo','fooMethod'], //数组或者对象,注入到子组件
  10. mounted() {
  11. this.fooMethod()
  12. console.log(this.foo)
  13. }
  14. //在父组件下面所有的子组件都可以利用inject

provide 和 inject 绑定并不是可响应的。这是官方刻意为之的。 然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的,对象是因为是引用类型

  1. //父组件:
  2. provide: {
  3. foo: '这是 foo'
  4. },
  5. mounted(){
  6. this.foo='这是新的 foo'
  7. }
  8. // 子或者孙子组件
  9. inject: ['foo'],
  10. mounted() {
  11. console.log(this.foo) //子组件打印的还是'这是 foo'
  12. }
  13. // 父组件
  14. provide() {
  15. return {
  16. staticValue: this.staticValue, // 直接返回值,不可响应
  17. staticObject: this.staticObject, // 返回一个对象,可响应
  18. getReactiveValue: () => this.staticValue // 返回一个对象的函数,可响应
  19. }
  20. },
  21. // 子组件
  22. inject: ["staticValue", "getReactiveValue", "staticObject"],
  23. computed: {
  24. reactiveValue() {
  25. return this.getReactiveValue(); // 返回注入的对象函数,通过计算属性来监听值的变化
  26. },
  27. },

所以provide返回一个对象或者函数是可以响应的, 因为对象和函数是引用类型, 实际上改变也不是vue做的,而是JS的引用类型特性

6.parent和children

7.$refs

  1. // 父组件
  2. <home ref="home"/>
  3. mounted(){
  4. console.log(this.$refs.home) //即可拿到子组件的实例,就可以直接操作 data 和 methods
  5. }

8 $root

9 sync

  1. // 父组件
  2. <home :title.sync="title" />
  3. //编译时会被扩展为
  4. <home :title="title" @update:title="val => title = val"/>
  5. // 子组件
  6. // 所以子组件可以通过$emit 触发 update 方法改变
  7. mounted(){
  8. this.$emit("update:title", '这是新的title')
  9. }

10.v-slot

2.6.0 新增 1.slot,slot-cope,scope 在 2.6.0 中都被废弃,但未被移除 2.作用就是将父组件的 template 传入子组件 3.插槽分类: A.匿名插槽(也叫默认插槽): 没有命名,有且只有一个;

  1. // 父组件
  2. <todo-list>
  3. <template v-slot:default>
  4. 任意内容
  5. <p>我是匿名插槽 </p>
  6. </template>
  7. </todo-list>
  8. // 子组件
  9. <slot>我是默认值</slot>
  10. //v-slot:default写上感觉和具名写法比较统一,容易理解,也可以不用写

B.具名插槽: 相对匿名插槽组件slot标签带name命名的;

  1. // 父组件
  2. <todo-list>
  3. <template v-slot:todo>
  4. 任意内容
  5. <p>我是匿名插槽 </p>
  6. </template>
  7. </todo-list>
  8. //子组件
  9. <slot name="todo">我是默认值</slot>

C.作用域插槽: 子组件内数据可以被父页面拿到(解决了数据只能从父页面传递给子组件)

  1. // 父组件
  2. <todo-list>
  3. <template v-slot:todo="slotProps" >
  4. {{slotProps.user.firstName}}
  5. </template>
  6. </todo-list>
  7. //slotProps 可以随意命名
  8. //slotProps 接取的是子组件标签slot上属性数据的集合所有v-bind:user="user"
  9. // 子组件
  10. <slot name="todo" :user="user" :test="test">
  11. {{ user.lastName }}
  12. </slot>
  13. data() {
  14. return {
  15. user:{
  16. lastName:"Zhang",
  17. firstName:"yue"
  18. },
  19. test:[1,2,3,4]
  20. }
  21. },
  22. // {{ user.lastName }}是默认数据 v-slot:todo 当父页面没有(="slotProps")

11 EventBus

1.就是声明一个全局Vue实例变量 EventBus , 把所有的通信数据,事件监听都存储到这个变量上; 2.类似于 Vuex。但这种方式只适用于极小的项目 3.原理就是利用on和on和emit 并实例化一个全局 vue 实现数据共享

  1. // 在 main.js
  2. Vue.prototype.$eventBus=new Vue()
  3. // 传值组件
  4. this.$eventBus.$emit('eventTarget','这是eventTarget传过来的值')
  5. // 接收组件
  6. this.$eventBus.$on("eventTarget",v=>{
  7. console.log('eventTarget',v);//这是eventTarget传过来的值
  8. })

可以实现平级,嵌套组件传值,但是对应的事件名eventTarget必须是全局唯一的

12 broadcast和dispatch

vue 1.x 有这两个方法,事件广播和派发,但是 vue 2.x 删除了 下面是对两个方法进行的封装

  1. function broadcast(componentName, eventName, params) {
  2. this.$children.forEach(child => {
  3. var name = child.$options.componentName;
  4. if (name === componentName) {
  5. child.$emit.apply(child, [eventName].concat(params));
  6. } else {
  7. broadcast.apply(child, [componentName, eventName].concat(params));
  8. }
  9. });
  10. }
  11. export default {
  12. methods: {
  13. dispatch(componentName, eventName, params) {
  14. var parent = this.$parent;
  15. var name = parent.$options.componentName;
  16. while (parent && (!name || name !== componentName)) {
  17. parent = parent.$parent;
  18. if (parent) {
  19. name = parent.$options.componentName;
  20. }
  21. }
  22. if (parent) {
  23. parent.$emit.apply(parent, [eventName].concat(params));
  24. }
  25. },
  26. broadcast(componentName, eventName, params) {
  27. broadcast.call(this, componentName, eventName, params);
  28. }
  29. }
  30. }

13 路由传参

a:

  1. // 路由定义
  2. {
  3. path: '/describe/:id',
  4. name: 'Describe',
  5. component: Describe
  6. }
  7. // 页面传参
  8. this.$router.push({
  9. path: `/describe/${id}`,
  10. })
  11. // 页面获取
  12. this.$route.params.id

b:

  1. // 路由定义
  2. {
  3. path: '/describe',
  4. name: 'Describe',
  5. component: Describe
  6. }
  7. // 页面传参
  8. this.$router.push({
  9. name: 'Describe',
  10. params: {
  11. id: id
  12. }
  13. })
  14. // 页面获取
  15. this.$route.params.id

c:

  1. // 路由定义
  2. {
  3. path: '/describe',
  4. name: 'Describe',
  5. component: Describe
  6. }
  7. // 页面传参
  8. this.$router.push({
  9. path: '/describe',
  10. query: {
  11. id: id
  12. `}
  13. )
  14. // 页面获取
  15. this.$route.query.id

三种方案对比 方案二参数不会拼接在路由后面,页面刷新参数会丢失 方案一和三参数拼接在后面,丑,而且暴露了信息

14 Vue.observable