Vue个人整理

221 阅读1分钟

Vue相关文章

生命周期图示

life cycle top life cycle bottom

对生命的周期的理解

  • 模板编译在created生命周期之后,在此之前vue的语法还没有被编译,也就是说,动态设置class,v-for,@enent,:prototype,等等这些都不生效

事件处理

内联语句

  • 例如,@click='handle(123,$event)'

$event

原生DOM中的$event

  • 原生DOM中传入进来的$event,指的是原生事件对象

组件中的$event

有的时候用一个事件来抛出一个特定的值是非常有用的。这时可以使用 $emit 的第二个参数来提供这个值:

  • 如果事件处理器只接收一个值,那么可以不需要在事件处理器上写参数,例如
父组件中:
<blog-post
  ...
  v-on:enlarge-text="onEnlargeText"
></blog-post>

methods: {
  onEnlargeText: function (enlargeAmount) {
    this.postFontSize += enlargeAmount
  }
}

组件blog-post:
<button v-on:click="$emit('enlarge-text', 0.1)">
  Enlarge text
</button>
  • 如果事件处理器没有写成内联语句,那么在此事件处理器上可以接收任意个参数,例如:
<blog-post
  ...
  v-on:enlarge-text="onEnlargeText"
></blog-post>

onEnlargeText: function (...arr) {
    console.log(arr)
    console.log(arguments)
    // 你会发现在子组件中调用$emit('enlarge-text',a,b,c...)传了多少个参数便能接受多少个参数,arguments和arr中就有多少项
}
  • 如果写成内联语句
    • 那么内联语句中定义了几个参数,事件处理器就接收几个参数
    • arguments中参数的个数,是内联语句中参数个数,也就是接收参数的个数
    • 接收的顺序不能乱,第几个传入的$event,就要第几个接受$event,其它参数同此
    • 内联语句中$event,是子组件传进来n个参数中的第一个,其它的参数不做接收
    • 例如:
父组件:
 <SelectTree
    @check="onTreeCheck($event,scope.$index)"
    @temporarySave='temporarySave(scope.$index, $event)'
  />
  
  // 修改值
  onTreeCheck($event, index) {
    const item = this.tableData[index]
    this.$set(this.tableData, index, {
      ...item,
      tags: $event
    })
  }
  
  temporarySave(rowIndex, $event){
    if(!$event){
      const data = this.tableData.find((item, index) => index === rowIndex )
      this.?(this.$AI.temporarySave(data.id), {
        "tagIds": data.tags
      }).then( res => {
        if(data.tags.length){
          data.marked = true
        } else {
          data.marked = false
        }
      })
    }
  },
  
  SelectTree组件:
  this.$emit('check', [4],21323,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2)
  this.$emit('temporarySave', false)

事件修饰符

  在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的

  • .stop 阻止事件继续传播
  • .prevent 阻止默认行为
  • 等等

修饰符可以串联

  • 例如:<a v-on:click.stop.prevent="doThat">阻止传播和默认行为

watch

  • 处理异步
  • 可以用来监听data或者props的变化
  • 不可以和computed重名
  • 监听对象的时候除非,引用地址换了,否则要加deep:true,才能监听到里面具体的变化,上代码
<template>
  <div>
    <input type="text" v-model="obj.c">
  </div>
</template>
<script>
export default {
  name: 'children',
  data() {
    return {
      obj: {c: 123}
    }
  },
  watch: {
    obj: {
      /**
       * newV 新的值
       * oldV 老的值
       * 对象的时候,newV和oldV是一样的值,要写deep:true才能监听得到或者换引用空间地址才能监听得到
       * 数组不需要deep:true, 新的值和老的值不一样
       */
      handler(newV, oldV) {
        console.log(newV, "newV")
        console.log(oldV, 'oldV')
      },
      deep: true
    }
  }
}
</script>
  • 如果不加deep那么直接改变c的值是不会被监听到的
  • 数组不需要加deep: true

Vue的响应原理

  • 由于 Vue 会在初始化实例时对属性执行 getter/setter 转化,所以属性必须在 data 对象上存在才能让 Vue 将它转换为响应式的。
  • Vue 不允许动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, propertyName, value)/ this.set(this.someObject,b,2)方法向嵌套对象添加响应式属性.(vm.set(this.someObject,'b',2)方法向嵌套对象添加响应式属性.(vm.set 实例方法,这也是全局 Vue.set 方法的别名
 // 代替 `Object.assign(this.someObject, { a: 1, b: 2 })
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })

注册组件

  • 全局注册组件
    • Vue.component('componentName', {...options})
    • 全局注册必须在根Vue示例(new Vue)创建之前发生。
  • 局部注册组件
    • 在.vue文件中引用,并注册{..., components: {...}, ...}

props

大小写

  • 在HTML结构中要kebab-case(短横线)写法<component test-prop="hello"></component>
  • 在JS中可以是camelCase(驼峰写法),props:["testProp"]

写法

  • 动态写法
    • v-bin:property=property 简写 :property=property
    • v-bind="post", post = { id: 1, test: 2 } 等价 :id="post.id" :test="post.test"
  • 静态写法
    • <component test="testData"></component>

单项数据流

  • 子组件不能更改传入进来的props,但是可以用v-model,.sync去更改父组件的数据,这不属于子组件直接更改props

props 验证

  • 我基本上没有做过验证,自己用都会传入规范的值

非Props的Attribute

一个非 prop 的 attribute 是指传向一个组件,但是该组件并没有相应 prop 定义的 attribute。 那么这些没有被定义的attribute会被写在这个组件的根元素上 例如,想象一下你通过一个 Bootstrap 插件使用了一个第三方的 <bootstrap-date-input> 组件,这个插件需要在其 <input> 上用到一个 data-date-picker attribute。我们可以将这个 attribute 添加到你的组件实例上: <bootstrap-date-input data-date-picker="activated"></bootstrap-date-input> 然后这个 data-date-picker="activated" attribute 就会自动添加到 <bootstrap-date-input>的根元素上。

替换/合并已有的Attribute

对于绝大多数attrbute来说,从外部提供的属性会替换掉组件内部设好的属性。比如:传入的type="text"会替换点组件上type="data",庆幸的是classstyle的attribute会智能一些,即两边的值会被合并起来,从而得到最终的值, example:

<component class="testName"></component>

component组件内结构

<input class="myInput"></input>

那么最后得到class值是myInput testName

禁用继承Attribute值

如果你不希望组件的根元素继承attribute,你可以在组建的预设中设置inheritAttrs: false,
example: Vue.component('my-compnenet',{inheritAttrs: false, ...})
inheritAttrs: false不会影响class和style的绑定, inheritAttrs: fase$attrs,就可以手动解决这些attribute会被赋予哪个元素。在撰写基础组件的时候会用到的: example:

Vue.component('base-input', {
  inheritAttrs: false,
  props: ['label', 'value'],
  template: `
    <label>
      {{ label }}
      <input
        v-bind="$attrs"
        v-bind:value="value"
        v-on:input="$emit('input', $event.target.value)"
      >
    </label>
  `
})

当然你也可以只绑定$attrs里面的单个或多个属性 exmpale:

  inheritAttrs: false,
  props: ['label', 'value'],
  template: `
    <label>
      {{ label }}
      <input
        my-name="$attrs.propertyName"
        my-name1="$attrs.propertyName1"
        v-bind:value="value"
        v-on:input="$emit('input', $event.target.value)"
      >
    </label>
  `
})