prop和$ref之間的區別:
prop 着重於數據的傳遞,它並不能調用子組件里的屬性和方法。像創建文章組件時,自定義標題和內容這樣的使用場景,最適合使用prop。
$ref 着重於索引,主要用來調用子組件里的屬性和方法,其實並不擅長數據傳遞。而且ref用在dom元素的時候,能使到選擇器的作用,這個功能比作為索引更常有用到。
props 父組件傳值子組件
父組件傳值
//props示例(vue) <template> <div id="app"> <child :message="message"></child> 動態傳遞
<child message="傳遞的內容"></child> 靜態傳遞
</div> </template> <script> import Child from "./Child"; export default { components: {Child}, name: "main-page", data() { return { message:{ type:1, name:'Admin', }, a:2, b:4, c:'lalal'+Math.random(), title:'', info:'我是來自父組件', msg:'默認' } }, created() {}, mounted(){}, methods: {} } </script> <style lang="scss" scoped> </style>
子組件接收父組件傳值
<template> <div> {{message}} <!--<slot></slot>--> </div> </template> <script> export default { name: "child", props:['message'], data() { return { title:'' } }, mounted() {}, methods:{} } </script> <style lang="scss" scoped> </style>
父組件code引用子組件,通過props可以實現傳值。可以傳遞string , number , object,表達式。對於子組件接受父組件props,可以直接使用props:[‘xxxx’]格式,為了更嚴謹,可以使用如下方式:
<script> export default { name: "child", // props:['message'], props:{ message:{ type:Object, default:function () { return {} } } }, data() { return { title:'' } }, mounted() { // this.$emit('showMessage','我是來自子組件') }, methods:{ } } </script>
$emit 子組件向父組件傳值
props、ref 實現的都是父組件=>子組件之間的通信,而$emit則可實現子組件向父組件的通信, $emit應用的范圍較為廣泛。
子組件傳值給父組件
template>
<div>
<input ref="myBtn"></input>
</div>
</template>
<script>
export default {
name: "index",
data() {
return {
info:'ref可以獲取到元素哦~'
}
},
mounted() {
this.$emit('showMessage','我是來自子組件')
},
methods:{
}
}
</script>
父組件接收子組件傳值
<template>
<div id="app">
<child @showMessage="showMessage"></child>
</div>
</template>
<script>
import Child from "./Child";
export default {
components: { Child},
name: "main-page",
data() {
return {
message:{
type:1,
name:'Admin',
},
fromchildinfo :'我是來自父組件',
msg:'默認'
}
},
created() {
},
mounted(){
},
methods: {
showMessage (data) { this.fromchildinfo = data },
}
}
</script>
$ref 的使用
說明:vm.$refs 一個對象,持有已注冊過 ref 的所有子組件(或HTML元素)
使用:在 HTML元素 中,添加ref屬性,然后在JS中通過vm.$refs.屬性來獲取
注意:如果獲取的是一個子組件,那么通過ref就能獲取到子組件中的data和methods
添加ref屬性
<div id="app"> <h1 ref="h1Ele">這是H1</h1> <hello ref="ho"></hello> <button @click="getref">獲取H1元素</button>
</div>
獲取注冊過 ref 的所有組件或元素 methods: { getref() { // 表示從 $refs對象 中, 獲取 ref 屬性值為: h1ele DOM元素或組件 console.log(this.$refs.h1Ele.innerText); this.$refs.h1ele.style.color = 'red';// 修改html樣式 console.log(this.$refs.ho.msg);// 獲取組件數據 console.log(this.$refs.ho.test);// 獲取組件的方法 } }
<input ref="count" type="text" v-model="active.name" required name="name" value="">
這樣在vue中我們可以使用$ref來獲取dom節點,進行一些dom的操作
下面示例:控制input輸入框的文字個數
new Vue({
el:'#app',
data:{
active:{'name':''}
},
watch:{
active:{
handler:function(){
var _this = this;
var _sum = 4; //字數限制為4個
_this.$refs.count.setAttribute("maxlength",_sum);
},
deep:true
}
},
})
使用在子組件上,可以用來獲取子組件的屬性值,假設子組件里面都有一個屬性news
<!-- 父組件 -->
<div id="app">
<hdnews ref="hdnews"></hdnews>
<hdinfo ref="hdinfo"></hdinfo>
</div>
new Vue({
el:'#app',
mounted () {
console.log(this.$refs.hdnews.news); //獲取子組件的值
console.log(this.$refs.hdinfo.news);
this.$refs.msg.getMessage('我是子組件一!') //調用子組件的方法
}
})
<!-- 子組件 --> <template> <h3>{{message}}</h3> </template> <script> export default { data(){ return{ news:'我是子組件的數據' } }, methods:{ getMessage(m){ this.message=m; } } } </script>
$attr、 $listeners
場景提出:A、B、C三個組件,需要實現A=>B=>C,進行傳遞(結構較為簡單,無需使用vuex)。當然實現方式也可以$emit,一層一層傳遞下去,但這樣代碼顯得冗余。在vue2.4之后,提出 $attr、 $listeners ,可以實現快速傳遞。
組件A code:
<template>
<div id="app">
<son :info="info" @getData="getData"></son>
<div>{{msg}}</div>
</div>
</template>
<script>
import Son from "./son";
export default {
components: {
Son,
Test,
Child},
name: "main-page",
data() {
return {
message:{
type:1,
name:'Admin',
},
a:2,
b:4,
c:'lalal'+Math.random(),
title:'',
info:'我是來自父組件',
msg:'默認'
}
},
created() {
},
mounted(){
},
methods: {
getData (val) {
this.msg = val
},
}
}
</script>
<style lang="scss" scoped>
#app {
width: 375px;
height: 100%;
}
</style>
b組件
<template>
<temp-son v-bind="$attrs" v-on="$listeners"></temp-son>
</template>
<script>
import TempSon from "./tempSon";
export default {
components: {TempSon},
name: "son",
props:[]
}
</script>
<style scoped>
</style>
c組件
<template>
<div>
<h1 class="btn">{{this.$attrs.info}}</h1>
</div>
</template>
<script>
export default {
name: "temp-son",
mounted() {
this.$emit('getData','我來自孫子組件')
}
}
</script>
<style scoped>
</style>
$attr、 $listeners 的TypeScript寫法
A組件
<template>
<div class="home">
<img alt="Vue logo" src="@/assets/images/logo.png" />
<HelloWorld :info="info" @sunchangedata="getData" :msg="info" />
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import HelloWorld from "@/components/HelloWorld.vue"; // @ is an alias to /src
@Component({
components: {
HelloWorld
}
})
export default class Home extends Vue {
info = "你不是好人?";
getData(val:any){
this.info = val;
};
}
</script>
b組件
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>hello hello 我是來自子組件</p>
<Sun v-bind="$attrs" v-on="$listeners"></Sun>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
import Sun from "./sun.vue"; // @ is an alias to /src
@Component({
components:{
Sun
}
})
export default class HelloWorld extends Vue {
inheritAttrs = false;
@Prop() private msg!: string;
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
</style>
c組件
<template>
<div>
<p>sun組件</p>
<p>來自爺爺輩:{{ $attrs.info }}</p>
<button @click="$emit('sunchangedata','孫子說爺爺是好人')">點擊更改爺爺輩信息</button>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from "vue-property-decorator";
export default class Sun extends Vue {
}
</script>
<style>
</style>
