如何解决子组件属性设置在根元素上
应用场景:
当我们去调用组件时,会有一个需求是将一些属性传入子组件。当我们定义了props时,子组件可以接收这些属性并进行使用。但组件库的作者并不总能预见组件会被用于怎样的场景。组件可以接受任意的特性,而这些没有被定义当特性就会被添加到这个组件的根元素上。
例如:
//父组件
<template>
<child test="呵呵哒" placeholder="呵呵呵" ></child>
</template>
<script>
import child from "./child";
export default {
name: "App",
components:{child}
};
</script>
//子组件
<template>
<div class="child">
<input type="text" :value="test" />
</div>
</template>
<script>
export default {
name: "child",
props: ["test"],
};
</script>
上述代码执行后的结果为:
我们发现placeholder被加在了根元素上,如果我们想把placeholder加在input上该怎么做呢?
Vue有一个inheritAttrs的属性,可以在子组件上进行设置,配合$attrs的属性。我们就可以随心所欲的将自定义属性在任何元素上添加。
//子组件改造
<template>
<div class="child">
<input type="text" :value="test" v-bind="$attrs"/> <!--用v-bind来继承$attrs-->
</div>
</template>
<script>
export default {
name: "child",
inheritAttrs:false,//禁用特性继承
props: ["test"],
data() {
return {};
}
};
</script>
改造过后我们就可以将placeholder放在input上,而不是根元素div上了。
class的绑定
应用场景:
当我们想指定某个class根据状态进行渲染,其余的class是默认直接渲染的时候,可以使用以下方法
<template>
<div class="app">
<p :class="[{red:isRed},'font32','bgBlue']">这是一段测试文本</p>
</div>
</template>
<script>
export default {
name: "App",
data(){
return{
isRed:true
}
}
};
</script>
<style>
.red{
color:red;
}
.font32{
font-size: 32px;
}
.bgBlue{
background: blue;
}
</style>
对于未提前定义data变量的新增
应用场景:
Vue中data的变量是响应式的,即我们对变量进行了修改会触发对应视图的重新渲染。但是他有一个前提条件就是,我们需要提前在data中定义好这个变量才能在以后修改这个变量时触发相应。
但在开发时,我们有时候无法预见我们需要提前定义多少变量。当后端返回的某个数据我们需要在data中进行保存使用时,就无法实现响应式。
Vue为我们提供了一些API以对应这种场景的需要,但是需要注意的是,他只能对引用类型的变量进行使用,例如data{obj:{a:123}},而对于data{a:123}这种根属性是无法使用的。
<template>
<div class="app">
<p>{{foo.a}}</p>
<p v-if="foo.b">{{foo.b}}</p>
</div>
</template>
<script>
export default {
name: "App",
data(){
return{
foo:{
a:'这是a'
}
}
},
mounted(){
setTimeout(()=>{
//错误写法 无法被页面响应
this.foo.b='这是b';
//正确写法
this.$set(this.foo,'b','这是b');
},2000)
}
};
</script>
这样的话,在2秒后,页面会渲染"这是b"这句话。
data数组的修改
应用场景:
当我们想对data里的数组进行修改时,可以借助Vue的变异方法
push(),pop(),shift(),unshift(),splice(),sort(),reverse()。或者非变异方法filter(), concat() 和 slice() 。
变异方法与非变异方法的区别在于,变异方法直接修改数组,而非变异方法返回新数组。
但是由于js的限制,vue无法修改以下数组:
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的
为了解决第一类问题,以下三种方式都可以实现和
Vue.set(vm.items, indexOfItem, newValue)
vm.items.splice(indexOfItem, 1, newValue)
vm.$set(vm.items, indexOfItem, newValue)
如果想要改变数组长度的话 可以
vm.items.splice(newLength)
v-model的使用
v-model只是vue的一个语法糖,v-model 会忽略所有表单元素的 value、checked、selected 特性的初始值而总是将 Vue 实例的数据作为数据来源。
v-model的使用有点类似于React的受控组件
当v-model作用在input或者textarea元素时,vue只是将input元素的value设置为绑定变量,并通过input元素的input事件将绑定变量的值修改为input元素的值。当我们添加了.lazy修饰符时,也只是将input事件改为了change事件
<input type="text" v-model="foo"/>
//其实就是
<input type="text" value="foo" @input="foo=this.value">
<input type="text" v-model.lazy="foo"/>
//其实就是
<input type="text" value="foo" @change="foo=this.value">
当v-model作用在radio元素时,vue会将value与绑定变量一致的radio设置为checked,触发change事件时,改变绑定变量的值为checked元素的value。
<input type="radio" value="test1" v-model="foo"/>
<input type="radio" value="test2" v-model="foo"/>
//其实就是
<input type="radio" value="test1" checked="this.value==foo" @change="foo=this.value">
<input type="radio" value="test2" checked="this.value==foo" @change="foo=this.value">
网友评论