欢迎来到小懒的博客~email:568705236@qq.com

往vue demo中的组件加入父子通信

2020/9/23 17:04:00站长

    前面我已经试过往vue的demo里面添加了vue-router和vuex。今天我就来把demo中的基础子控件增加一些动态操作。

    首先vue有直接的父子数据直接引用$parent和$children。直接上例子。

//app.vue
<template>
  <div id="app">

    <div>这是计数{{count}}</div>
    <p>
    <!-- 使用 router-link 组件来导航. -->
    <!-- 通过传入 `to` 属性指定链接. -->
    <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>

    <img alt="Vue logo" src="./assets/logo.png">

    <HelloWorld ref="hw" msg="Welcome to Your Vue.js App"/>
<!-- 增加部分 -->
	<div>
		<div>这里是父控件</div>
		<div><input type="button" value="子控件直接赋予数据" @click="TC" /></div>
		<div v-for="item in allquestionlist.page_1[0].content" :key="item.id">
			选择框是否选中:{{ item.check }}
		</div>
	</div>
<!-- 结束增加部分 -->
  </div>
</template>
<script>

import HelloWorld from './components/HelloWorld.vue'
export default {
  name: 'App',
  components: {
    HelloWorld
  },
  data(){
   return {
	count:this.$store.state.count, //赋予计数器的值
//增加3个变量
	allquestionlist:{
		"page_1":[{
			content:[
				{id:1,check:false},
				{id:2,check:false},
				{id:3,check:false}
			]
		}]
	},
	studyInfo:{
		now_page:1
	},
	question:{
		index:0,
		content:[
			{id:1,name:"选项1"},
			{id:2,name:"选项2"},
			{id:3,name:"选项3"}
		]
	}
   }; 
  },
methods:{
     TC(){
            //console.log(this.$children);
//console.log(this.$refs["hw"]);
//这里使用refs是为了快速定位到子控件,因为用children的话需要逐个判断
	this.$refs["hw"].studyInfo= this.studyInfo;
	this.$refs["hw"].question = this.question;
       }
}
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>


//helloworld.vue
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <p>
      For a guide and recipes on how to configure / customize this project,<br>
      check out the
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
    </p>
    <h3>Installed CLI Plugins</h3>
    <ul>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
    </ul>
    <h3>Essential Links</h3>
    <ul>
      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
    </ul>
    <h3>Ecosystem</h3>
    <ul>
      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
    </ul>
    <!-- 增加部分,此处的model使用$parent来直接引用父控件的变量 -->
<div>这里是子控件</div>
<div v-for="(item,qindex) in question.content" :key="item.id">
    <input type="checkbox" v-model="$parent.allquestionlist['page_'+studyInfo.now_page][question.index].content[qindex].check" />item.name<br /> 
</div>
<!-- 结束增加部分,内容放在div.hello里面,模板一个根节点 -->
  </div>

</template>

<script>
"use strict" 
export default {
  name: 'HelloWorld',
  props: {
    msg: String,
    question:{
     type:Object,
    default:function () {
        return { content: [] }
      }
},
    studyInfo:{
     type:Object,
    default:function () {
        return { content: [] }
      }
}
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

    我在app.vue里面加了个按钮,点击按钮时,就直接修改子控件helloworld里面的变量。开始的时候,子控件的变量是默认空值,点击按钮后,就渲染出列表了。点击渲染的列表中的checkbox,因为checkbox的model是直接引用父控件的变量,所以父控件的变量会同步修改。

20200923_1.gif

    后面在说下按部就班的父子传递值方式,prop和$emit发起事件。这种形式一般用于组件是通用型的,以API的方式与父控件交换。当然这个情况用于prop非对象引用,传值类的使用。上代码。

//app.vue
<template>
  <div id="app">

    <div>这是计数{{count}}</div>
    <p>
    <!-- 使用 router-link 组件来导航. -->
    <!-- 通过传入 `to` 属性指定链接. -->
    <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
    <router-link to="/foo">Go to Foo</router-link>
    <router-link to="/bar">Go to Bar</router-link>
  </p>
  <!-- 路由出口 -->
  <!-- 路由匹配到的组件将渲染在这里 -->
  <router-view></router-view>

    <img alt="Vue logo" src="./assets/logo.png">

    <HelloWorld ref="hw" msg="Welcome to Your Vue.js App" :studyInfo="studyInfo" :question="question" :checkstr="checkstr"  @update:checkstr="checkstr = $event"/>
<!-- 增加部分 -->
	<div>
		<div>这里是父控件 </div>
		
		<div>checkstr:{{checkstr}}</div>
	</div>
<!-- 结束增加部分 -->
  </div>
</template>
<script>
"use strict" 
import HelloWorld from './components/HelloWorld.vue'
export default {
  name: 'App',
  components: {
    HelloWorld
  },
  data(){
   return {
	count:this.$store.state.count, //赋予计数器的值
//增加3个变量
	allquestionlist:{
		"page_1":[{
			content:[
				{id:1,check:true},
				{id:2,check:false},
				{id:3,check:false}
			]
		}]
	},
	studyInfo:{
		now_page:1
	},
	question:{
		index:0,
		content:[
			{id:1,name:"选项1"},
			{id:2,name:"选项2"},
			{id:3,name:"选项3"}
		]
	},
                checkstr:'未选中'
   }; 
  },
methods:{

}
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>


//helloworld.vue
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <p>
      For a guide and recipes on how to configure / customize this project,<br>
      check out the
      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
    </p>
    <h3>Installed CLI Plugins</h3>
    <ul>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
    </ul>
    <h3>Essential Links</h3>
    <ul>
      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
    </ul>
    <h3>Ecosystem</h3>
    <ul>
      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
    </ul>
<div>这里是子控件 {{checkstr}}</div>
<div v-for="(item,qindex) in question.content" :key="item.id">
    <input type="checkbox" @change="function(e){c1(e,qindex)}" />item.name<br /> 
</div>
  </div>

</template>

<script>
"use strict" 
export default {
  name: 'HelloWorld',
  props: {
    msg: String,
    question:{
     type:Object,
    default:function () {
        return { content: [] }
       }
    },
    studyInfo:{
     type:Object,
    default:function () {
        return { content: [] }
      }
    },
    checkstr:{
       type:String,
       default:function(){
         return '';
       }
     }
  },
   methods:{
       c1(e){
         //console.log(e.target.checked);
         this.checkstr = e.target.checked?'选中':'未选中';
         this.$emit("update:checkstr",this.checkstr);
       }
   }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>


 20200923_2.gif

    prop传对象的话就会直接自动变化,但就容易被子控件随意修改了值。




赞赏