vue问题总结1
双向绑定
vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
var obj = {}
var val = "val"//txt属性默认值
Object.defineProperty(obj, 'txt', {
get: function () {
console.log("diaoyong")
return val
},
set: function (newValue) {
document.getElementById('txt').value = newValue
document.getElementById('show').innerHTML = newValue
}
})
document.addEventListener('keyup', function (e) {
obj.txt = e.target.value
})
为什么在 Vue3.0 采用了 Proxy,抛弃了 Object.defineProperty?
Object.defineProperty 本身有一定的监控到数组下标变化的能力,但是在 Vue 中,从性能/体验的性价比考虑,尤大大就弃用了这个特性(Vue 为什么不能检测数组变动 )。为了解决这个问题,经过 vue 内部处理后可以使用以下几种方法来监听数组
push();
pop();
shift();
unshift();
splice();
sort();
reverse();
由于只针对了以上 7 种方法进行了 hack 处理,所以其他数组的属性也是检测不到的,还是具有一定的局限性。
Object.defineProperty 只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。Vue 2.x 里,是通过 递归 + 遍历 data 对象来实现对数据的监控的,如果属性值也是对象那么需要深度遍历,显然如果能劫持一个完整的对象是才是更好的选择。Proxy 可以劫持整个对象,并返回一个新的对象。Proxy 不仅可以代理对象,还可以代理数组。还可以代理动态增加的属性。
如果在created中操作dom
this.$nextTick
穿透属性
$attrs包含从父组件传过来的属性,但不包含子组件中prop中的属性以及class和style,所以对于那些html元素原生属性,可以不用再子组件中声明,直接从父组件中传进来就好
// 子组件 <template> <div> <input type="text" name="" id="" v-bind="$attrs" v-on='listeners'/> </div> </template> props: { test: { type: String, default: '123456' } }, created () { console.log(`props:%o`, this.$props) // {test: '测试'} console.log('attrs:%o', this.$attrs) // {value: '测试'} }, // 父组件 <myInput :value="value" :class="class_" :style='style' :test='test' @input1="input"/> data () { return { style: { color: 'red' }, value: '测试', class_: 'test', test: '测试' } }
由于在子组件中input并不是根元素,默认情况下父组件的不被认作 props 的特性绑定将会“回退”且作为普通的 HTML 特性应用在子组件的根元素上,例如根节点div会有value="测试"的属性,所以子组件需要设置 inheritAttrs: false去掉根元素默认行为,这样就可以通过实例属性 $attrs 可以让这些特性生效,且可以通过 v-bind 显性的绑定到非根元素上。
export default { inheritAttrs: true }
自定义组件v-model
一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,但是像单选框、复选框等类型的输入控件可能会将 value attribute 用于不同的目的。model 选项可以用来避免这样的冲突
ref注册子组件 父组件通过$refs.funcname调用子组件方法
子组件通过$emit
vue修饰符
v-model的修饰符
.lazy
在默认情况下,v-model 在每次 input 事件触发后将输入框的值与数据进行同步 ,我们可以添加 lazy 修饰符,从而转变为使用 change事件进行同步:
<!-- 在“change”时而非“input”时更新 --><input v-model.lazy="msg" >
.number
如果想自动将用户的输入值转为数值类型,可以给 v-model 添加 .number修饰符:
<input v-model.number="age" type="number">
.trim
如果要自动过滤用户输入的首尾空白字符,可以给 v-model 添加 trim 修饰符:
<input v-model.trim="msg">
v-on的修饰符
.stop
该修饰符将阻止事件向上冒泡。同理于调用 event.stopPropagation() 方法
.prevent
该修饰符会阻止当前事件的默认行为。同理于调用 event.preventDefault() 方法
.self
该指令只当事件是从事件绑定的元素本身触发时才触发回调
.one
该修饰符表示绑定的事件只会被触发一次
. capture
即是给元素添加一个监听器,当元素发生冒泡时,先触发带有该修饰符的元素。若有多个该修饰符,则由外而内触发。
就是谁有该事件修饰符,就先触发谁。
父子组件的生命周期执行顺序
1.加载渲染过程
| 父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted |
|---|
2.子组件更新过程
| 父beforeUpdate->子beforeUpdate->子updated->父updated | |
|---|---|
3.销毁过程
| 父beforeDestroy->子beforeDestroy->子destroyed->父destroyed | |
|---|---|
computed 计算属性,不需要调用可以直接在dom中使用 不支持异步 可以传参数
1.是计算值
2.应用:就是简化tempalte里面{{}}计算和处理props或$emit的传值,如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一
3.具有缓存性,只有依赖数据发生改变,才会重新进行计算,页面重新渲染值不变化,计算属性会立即返回之前的计算结果,而不必再次执行函数
给计算属性的值赋值必须有set方法
watch监听数据变化
1.是观察的动作 支持异步,监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值
2.应用:监听props,$emit或本组件的值执行异步操作,当一个属性发生变化时,需要执行对应的操作;一对多;
3.无缓存性,页面重新渲染时值不变化也会执行
同:
computed和watch都是观察页面的数据变化的。
异:
computed只有当页面数据变化时才会计算,当数据没有变化时,它会读取缓存。而watch每次都需要执行函数,methods也是每次都需要执行
数据变化时执行异步操作,这个时候使用watch是合适的
常用API指令
v-show v-if v-for v-on v-bind v-model v-slot
Vue.use
Vue.delete 删除对象属性,如果对象是响应式的,确保删除会触发视图更新。
Vue.nextTick
Vue.set设置对象的属性。如果对象是响应式的,确保属性被创建后也是响应式的,同时触发视图更新。这个方法用于避开Vue不能检测属性被添加的限制。
如果你在Vue实例化后添加(或删除)一个属性(例如在方法或生命周期钩子中),Vue是不知道它的。
使用Vue.set设置一个新的对象属性。该方法确保将属性创建为一个响应式属性,并触发视图更新。
对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property。例如,对于:
Vue.set(vm.someObject, 'b', 2)
您还可以使用 vm.$set 实例方法,这也是全局 Vue.set 方法的别名:
this.$set(this.someObject,'b',2)
有时你可能需要为已有对象赋值多个新 property,比如使用 Object.assign() 或 _.extend()。但是,这样添加到对象上的新 property 不会触发更新。在这种情况下,你应该用原对象与要混合进去的对象的 property 一起创建一个新的对象。
// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。如果数据项的顺序被改变,Vue将不是移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
Vue 组件 data 为什么必须是函数 ?
new Vue()实例中,data 可以直接是一个对象,为什么在 vue 组件中,data 必须是一个函数呢?
因为组件是可以复用的,JS 里对象是引用关系,如果组件 data 是一个对象,那么子组件中的 data 属性值会互相污染,产生副作用。
所以一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝。new Vue 的实例是不会被复用的,因此不存在以上问题。

浙公网安备 33010602011771号