Vue相关文章
生命周期图示
对生命的周期的理解
- 模板编译在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 实例方法,这也是全局 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: {...}, ...}
- 在.vue文件中引用,并注册
props
大小写
- 在HTML结构中要kebab-case(短横线)写法
<component test-prop="hello"></component> - 在JS中可以是camelCase(驼峰写法),
props:["testProp"]
写法
- 动态写法
v-bin:property=property 简写 :property=propertyv-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",庆幸的是class和style的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>
`
})