1. <style>
  2. * {
  3. margin: 0;
  4. padding: 0;
  5. }
  6. .icons {
  7. display: inline-block;
  8. width: 20px;
  9. height: 20px;
  10. background: url("./star.png") no-repeat;
  11. background-position: 0px 0px;
  12. background-size: 100%;
  13. /* background-color: burlywood; */
  14. }
  15. /* .icons:hover {
  16. background-position: 0px -30px;
  17. } */
  18. .active {
  19. background-position: 0px -30px;
  20. }
  21. </style>
  22. <body>
  23. <script src='./vue.js'></script>
  24. <div id='myApp'>
  25. <h1>平均分:{{myFen}} </h1>
  26. <div>
  27. <input
  28. type="number"
  29. v-for="item,i in score.length"
  30. :key="i"
  31. ref="item"
  32. style="margin: 5px;"
  33. v-model.number="score[i]"
  34. min="0" max="5"
  35. >{{score}}
  36. </div>
  37. <my-com1
  38. v-for="item,i in gradeList"
  39. :key="item"
  40. @mymark="getMark"
  41. :dataa="score[i]"
  42. :index="i"
  43. >
  44. {{item}}
  45. </my-com1>
  46. </div>
  47. <!-- 组件模板 -->
  48. <template id='myTem'>
  49. <!-- <div> -->
  50. <ul>
  51. <li style="list-style: none;">
  52. <slot></slot> :
  53. <i
  54. class="icons"
  55. v-for="item,i in 5"
  56. :class="item<=temp?'active':''"
  57. 注释="鼠标悬停时,得到临时评分"
  58. @mouseenter="temp=item"
  59. 注释="鼠标离开时,临时分数还原成真实分数"
  60. @mouseleave="temp=dataa"
  61. 注释="点击星星时,得到真实评分"
  62. @click="bright(item)"
  63. ></i>
  64. <b style="color: coral;">{{dataa}} 分:</b>
  65. <!-- 评分是1-5 评价信息索引是0-4 刚好差了1 -->
  66. <strong>{{appraises[dataa-1]}} </strong>
  67. </li>
  68. </ul>
  69. <!-- </div> -->
  70. </template>
  71. <script>
  72. Vue.component('myCom1', {
  73. template: '#myTem',
  74. props: ["dataa", "index"],
  75. data() {
  76. return {
  77. // temp是临时的分数,用于展示鼠标悬停时显示的分数
  78. temp: this.dataa,
  79. appraises: ["非常差", "一般差", "还凑合", "一般好", "非常好"]
  80. }
  81. },
  82. methods: {
  83. bright(item) {
  84. console.log(item);
  85. // 再次强调,单向数据流限制,子组件千万不要直接改数据
  86. // this.$set(this.mark,this.dataa,item)
  87. // 要发自定义事件, 把数据传给父组件,由父组件改
  88. this.$emit("mymark", {
  89. mark: item,
  90. i: this.index
  91. })
  92. }
  93. }
  94. })
  95. new Vue({
  96. el: '#myApp',
  97. data: {
  98. gradeList: ["商品评价", "物流评价", "客服评价", "快递小哥评价"],
  99. score: [1,2,3,4]
  100. },
  101. methods: {
  102. getMark(data) {
  103. console.log(data)
  104. // this.score[data.i] = data.mark
  105. this.$set(this.score, data.i, data.mark)
  106. }
  107. },
  108. mounted() {
  109. console.log(this.$refs.item) //有多个ref值相同的标签,会得到一个数组
  110. },
  111. computed: {
  112. myFen() {
  113. var fen = 0
  114. this.score.forEach(item => {
  115. fen += item * 1 / 4
  116. });
  117. return fen
  118. }
  119. }
  120. })
  121. </script>
  122. </body>

star.png

父子组件间的双向绑定

  1. <style>
  2. * {
  3. margin: 0;
  4. padding: 0;
  5. }
  6. .icons {
  7. display: inline-block;
  8. width: 20px;
  9. height: 20px;
  10. background: url("./star.png") no-repeat;
  11. background-position: 0px 0px;
  12. background-size: 100%;
  13. /* background-color: burlywood; */
  14. }
  15. /* .icons:hover {
  16. background-position: 0px -30px;
  17. } */
  18. .active {
  19. background-position: 0px -30px;
  20. }
  21. </style>
  22. <body>
  23. <script src='./vue.js'></script>
  24. <div id='myApp'>
  25. <h1>平均分:{{myFen}} </h1>
  26. <div>
  27. <input
  28. type="number"
  29. v-for="item,i in score.length"
  30. :key="i"
  31. ref="item"
  32. style="margin: 5px;"
  33. v-model.number="score[i]"
  34. min="0" max="5"
  35. >{{score}}
  36. </div>
  37. <my-com1
  38. v-for="item,i in gradeList"
  39. :key="item"
  40. 注释='@input="getMark"
  41. :value="score[i]"
  42. :index="i" '
  43. 注释="@input和:value实现了v-model, 所以以上对input自定义事件的绑定和对value自定义属性的绑定,可以简化为v-model"
  44. v-model="score[i]"
  45. >
  46. {{item}}
  47. </my-com1>
  48. </div>
  49. <!-- 组件模板 -->
  50. <template id='myTem'>
  51. <!-- <div> -->
  52. <ul>
  53. <li style="list-style: none;">
  54. <slot></slot> :
  55. <i
  56. class="icons"
  57. v-for="item,i in 5"
  58. :class="item<=temp?'active':''"
  59. 注释="鼠标悬停时,得到临时评分"
  60. @mouseenter="temp=item"
  61. 注释="鼠标离开时,临时分数还原成真实分数"
  62. @mouseleave="temp=value"
  63. 注释="点击星星时,得到真实评分"
  64. @click="bright(item)"
  65. ></i>
  66. <b style="color: coral;">{{value}} 分:</b>
  67. <!-- 评分是1-5 评价信息索引是0-4 刚好差了1 -->
  68. <strong>{{appraises[value-1]}} </strong>
  69. </li>
  70. </ul>
  71. <!-- </div> -->
  72. </template>
  73. <script>
  74. Vue.component('myCom1', {
  75. template: '#myTem',
  76. props: ["value"],
  77. data() {
  78. return {
  79. // temp是临时的分数,用于展示鼠标悬停时显示的分数
  80. temp: this.value,
  81. appraises: ["非常差", "一般差", "还凑合", "一般好", "非常好"]
  82. }
  83. },
  84. methods: {
  85. bright(item) {
  86. console.log(item);
  87. // 再次强调,单向数据流限制,子组件千万不要直接改数据
  88. // this.$set(this.mark,this.dataa,item)
  89. // 要发自定义事件, 把数据传给父组件,由父组件改
  90. // this.$emit("input", {
  91. // mark: item,
  92. // i: this.index
  93. // })
  94. // v-model绑定后, item会被直接赋值到 score[i]
  95. this.$emit("input", item)
  96. }
  97. }
  98. })
  99. new Vue({
  100. el: '#myApp',
  101. data: {
  102. gradeList: ["商品评价", "物流评价", "客服评价", "快递小哥评价"],
  103. score: [1,2,3,4]
  104. },
  105. methods: {
  106. // getMark(data) {
  107. // console.log(data)
  108. // // this.score[data.i] = data.mark
  109. // this.$set(this.score, data.i, data.mark)
  110. // }
  111. },
  112. mounted() {
  113. console.log(this.$refs.item) //有多个ref值相同的标签,会得到一个数组
  114. },
  115. computed: {
  116. myFen() {
  117. var fen = 0
  118. this.score.forEach(item => {
  119. fen += item * 1 / 4
  120. });
  121. return fen
  122. }
  123. }
  124. })
  125. </script>
  126. </body>