<style> * { margin: 0; padding: 0; } .icons { display: inline-block; width: 20px; height: 20px; background: url("./star.png") no-repeat; background-position: 0px 0px; background-size: 100%; /* background-color: burlywood; */ } /* .icons:hover { background-position: 0px -30px; } */ .active { background-position: 0px -30px; }</style><body> <script src='./vue.js'></script> <div id='myApp'> <h1>平均分:{{myFen}} </h1> <div> <input type="number" v-for="item,i in score.length" :key="i" ref="item" style="margin: 5px;" v-model.number="score[i]" min="0" max="5" >{{score}} </div> <my-com1 v-for="item,i in gradeList" :key="item" @mymark="getMark" :dataa="score[i]" :index="i" > {{item}} </my-com1> </div> <!-- 组件模板 --> <template id='myTem'> <!-- <div> --> <ul> <li style="list-style: none;"> <slot></slot> : <i class="icons" v-for="item,i in 5" :class="item<=temp?'active':''" 注释="鼠标悬停时,得到临时评分" @mouseenter="temp=item" 注释="鼠标离开时,临时分数还原成真实分数" @mouseleave="temp=dataa" 注释="点击星星时,得到真实评分" @click="bright(item)" ></i> <b style="color: coral;">{{dataa}} 分:</b> <!-- 评分是1-5 评价信息索引是0-4 刚好差了1 --> <strong>{{appraises[dataa-1]}} </strong> </li> </ul> <!-- </div> --> </template> <script> Vue.component('myCom1', { template: '#myTem', props: ["dataa", "index"], data() { return { // temp是临时的分数,用于展示鼠标悬停时显示的分数 temp: this.dataa, appraises: ["非常差", "一般差", "还凑合", "一般好", "非常好"] } }, methods: { bright(item) { console.log(item); // 再次强调,单向数据流限制,子组件千万不要直接改数据 // this.$set(this.mark,this.dataa,item) // 要发自定义事件, 把数据传给父组件,由父组件改 this.$emit("mymark", { mark: item, i: this.index }) } } }) new Vue({ el: '#myApp', data: { gradeList: ["商品评价", "物流评价", "客服评价", "快递小哥评价"], score: [1,2,3,4] }, methods: { getMark(data) { console.log(data) // this.score[data.i] = data.mark this.$set(this.score, data.i, data.mark) } }, mounted() { console.log(this.$refs.item) //有多个ref值相同的标签,会得到一个数组 }, computed: { myFen() { var fen = 0 this.score.forEach(item => { fen += item * 1 / 4 }); return fen } } }) </script></body>
star.png
父子组件间的双向绑定
<style> * { margin: 0; padding: 0; } .icons { display: inline-block; width: 20px; height: 20px; background: url("./star.png") no-repeat; background-position: 0px 0px; background-size: 100%; /* background-color: burlywood; */ } /* .icons:hover { background-position: 0px -30px; } */ .active { background-position: 0px -30px; }</style><body> <script src='./vue.js'></script> <div id='myApp'> <h1>平均分:{{myFen}} </h1> <div> <input type="number" v-for="item,i in score.length" :key="i" ref="item" style="margin: 5px;" v-model.number="score[i]" min="0" max="5" >{{score}} </div> <my-com1 v-for="item,i in gradeList" :key="item" 注释='@input="getMark" :value="score[i]" :index="i" ' 注释="@input和:value实现了v-model, 所以以上对input自定义事件的绑定和对value自定义属性的绑定,可以简化为v-model" v-model="score[i]" > {{item}} </my-com1> </div> <!-- 组件模板 --> <template id='myTem'> <!-- <div> --> <ul> <li style="list-style: none;"> <slot></slot> : <i class="icons" v-for="item,i in 5" :class="item<=temp?'active':''" 注释="鼠标悬停时,得到临时评分" @mouseenter="temp=item" 注释="鼠标离开时,临时分数还原成真实分数" @mouseleave="temp=value" 注释="点击星星时,得到真实评分" @click="bright(item)" ></i> <b style="color: coral;">{{value}} 分:</b> <!-- 评分是1-5 评价信息索引是0-4 刚好差了1 --> <strong>{{appraises[value-1]}} </strong> </li> </ul> <!-- </div> --> </template> <script> Vue.component('myCom1', { template: '#myTem', props: ["value"], data() { return { // temp是临时的分数,用于展示鼠标悬停时显示的分数 temp: this.value, appraises: ["非常差", "一般差", "还凑合", "一般好", "非常好"] } }, methods: { bright(item) { console.log(item); // 再次强调,单向数据流限制,子组件千万不要直接改数据 // this.$set(this.mark,this.dataa,item) // 要发自定义事件, 把数据传给父组件,由父组件改 // this.$emit("input", { // mark: item, // i: this.index // }) // v-model绑定后, item会被直接赋值到 score[i] this.$emit("input", item) } } }) new Vue({ el: '#myApp', data: { gradeList: ["商品评价", "物流评价", "客服评价", "快递小哥评价"], score: [1,2,3,4] }, methods: { // getMark(data) { // console.log(data) // // this.score[data.i] = data.mark // this.$set(this.score, data.i, data.mark) // } }, mounted() { console.log(this.$refs.item) //有多个ref值相同的标签,会得到一个数组 }, computed: { myFen() { var fen = 0 this.score.forEach(item => { fen += item * 1 / 4 }); return fen } } }) </script></body>