前面我已经试过往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是直接引用父控件的变量,所以父控件的变量会同步修改。
后面在说下按部就班的父子传递值方式,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>
prop传对象的话就会直接自动变化,但就容易被子控件随意修改了值。