Vue基础

Vue初识

官方文档

  • 配置vscode模板(File -> Preferences -> User Snippets -> 'html’大括号里面加入)
    后期只需输入prefix中的值即可匹配对应模板内容
"html": {
		"prefix": "html",
		"body": [
			"<!DOCTYPE html>",
			"<html lang=\"$1zh-CN\">",
			"\t<head>",
			"\t\t<title>$2</title>",
			"\t\t<meta charset=\"UTF-8\">",
			"\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">",
			"\t\t<link href=\"$3css/style.css\" rel=\"stylesheet\">",
			"\t</head>",
			"\t<body>",
			"\t$4",
			"\t</body>",
			"</html>"
			],
		"description": "HTML - Defines a template for a html5 document",
		"scope": "text.html"
	},
"Vue": {
        "prefix": "vue",
        "body": [
            "<!DOCTYPE html>",
            "<html lang=\"zh-CN\">",
            "\t<head>",
            "\t\t<title>$1</title>",
            "\t\t<meta charset=\"UTF-8\">",
            "\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">",
            "\t\t<script src=\"https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js\"></script>",
            "\t</head>",
			"\t<body>",
			"\t\t<div id=\"app\"></div>",
			"\t\t<script>",
			"\t\t\tvar vm = new Vue({",
			"\t\t\t\tel: \"#app\"",
			"\t\t\t\t$2",
			"\t\t\t})",
			"\t\t</script>",
            "\t</body>",
            "</html>"
        ],
        "description": "vue - Defines a template for a vue & html5 document"
    }
  • 基础语法学习

    • v-for:循环
      v-for=‘item in content_list’
    • v-on:绑定事件
      饭粒-点击事件绑定函数:v-on:click=‘handleBtnClick’ 可简写成–> @click=‘handleBtnClick’
    • v-model:绑定数据(模板),实现表单输入和应用状态之间的双向绑定
      v-model=‘inputValue’
    • v-if:条件判断
      v-if=“seen”
    • v-text:接字符串(如果是HTML标签不做转义),嵌在标签里面,可以在里面使用js语法,如v-text=’“name:” + name’
    • v-html:接字符串(如果是HTML标签会做转义),嵌在标签里面,可以在里面使用js语法,如v-html=’“name:” + name’
    • {{属性值}}:插值表达式,可以在里面使用js语法,如{{“name:” + name}}
    • v-once一次性地插值,当数据改变时,插值处的内容不会更新
    • 说明:只要是v-xxx接上的值是js表达式
    <div id="app">
        <input type="text" v-model='inputValue'>
        <button v-on:click='handleBtnClick'>提交</button>
        <ul>
            <li>{{"name:" + example}}</li>
            <li v-for='item in content_list'>{{item}}</li>
        </ul>
    </div>
    
    <script>
        var app = new Vue({
            el: '#app',
            data: {
                example: 'hhh',
                content_list: ['No.1', 'No.2', 'No.3'],
                inputValue: ''
            },
            methods: {
                handleBtnClick: function() {
                    this.content_list.push(this.inputValue),
                    this.inputValue = ''
                }
            }
        })
    </script>
    
    • Vue.component:创建全局组件(不用注册)
      Vue.component(“组件名”, {template: “…”})
    • 定义局部组件需要注册
    • v-bind:绑定名="绑定值":子组件向父组件传入绑定值(v-bind可省略不写,即:绑定名=“绑定值”)
    • this.$emit():向上层触发事件
    	<div id="app">
            <input type="text" v-model='inputValue'>
            <button v-on:click='handleBtnClick'>提交</button>
            <ul>
                <todo-item v-bind:content='item' 
                           v-bind:index='index' 
                           v-for='(item, index) in content_list'
                           @delete="handleItemDelete">
                </todo-item>
            </ul>
        </div>
    
        <script>
            // 定义全局组件
            // Vue.component("TodoItem", {
            //     props: ['content'],
            //     template: "<li>{{content}}</li>"
            // })
    
            // 定义局部组件
            var TodoItem = {
                props: ['content', 'index'],
                template: "<li @click='handleItemClick'>{{content}}</li>",
                methods: {
                    handleItemClick: function() {
                        this.$emit("delete", this.index);
                    }
                }
            }
    
            var app = new Vue({
                el: '#app',
                // 局部组件注册
                components: {
                    TodoItem: TodoItem
                },
                data: {
                    content_list: [],
                    inputValue: ''
                },
                methods: {
                    handleBtnClick: function() {
                        this.content_list.push(this.inputValue),
                        this.inputValue = ''
                    },
                    handleItemDelete: function(index) {
                        this.content_list.splice(index, 1)
                    }
                }
            })
        </script>
    
    • Vue实例属性 & 方法(接上栗)
      app.$data:Vue组件数据
      app.$el:Vue接管的组件
      app.$destroy():销毁Vue实例
  • Vue生命周期函数:Vue实例在某一个时间点会自动执行的函数(直接定义在Vue实例底下不用定义在methods中)

    • beforeCreate:在实例初始化之后调用
    • created:在实例创建完成后被立即调用
    • beforeMount:在挂载开始之前被调用
    • mounted:挂载之后被调用
    • beforeUpdate:数据更新之前调用
    • updated:数据更新之后调用
    • beforeDestroy:实例销毁之前调用
    • destroyed:实例销毁之后调用
      avatar
  • 计算属性、方法、侦听器(在Vue实例底下声明)

    • 计算属性:computed(调用不用带括弧) 有缓存功能,计算属性内的数据修改才会重新执行方法
    <li>{{getFullName}}</li>
    ...
    		computed: {
                getFullName: function() {
                    console.log('Getting fullName...')
                    return this.firstName + ' ' + this.lastName
                }
            }
    
    • 方法:methods (调用要带括弧) 没有缓存功能,任何数据修改都会重新执行方法
    <li>{{getFullName()}}</li>
    ...
    		getFullName: function() {
                console.log('Getting fullName...')
                return this.firstName + ' ' + this.lastName
            }
    
    • 监听器:watch 没有缓存功能
      当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
    <li>{{fullName}}</li>
    ...
    		data: {
                firstName: 'Z',
                lastName: 'fone',
                fullName: 'Z fone',
            },
            watch: {
                firstName: function(val) {
                    console.log('firstName change...');
                    this.fullName = val + ' ' + this.lastName;
                },
                lastName: function(val) {
                    console.log('lastName change...');
                    this.fullName = this.firstName + ' ' + val;
                }
            }
    
  • 样式绑定

    • class对象绑定
    <div id="app">
        <!-- <div @click='handleDivClick'
            :class='{ activated: isActivated }'> -->
    
        <div @click='handleDivClick'
            :class='[activated]'>
            Hello World!
        </div>
    </div>
    ...
    data: {
        // isActivated: false,
    
        activated: ""
    },
    methods: {
        handleDivClick: function() {
            // this.isActivated = !this.isActivated;
    
            // if (this.activated === 'activated') {
            //     this.activated = ''
            // }else {
            //     this.activated = 'activated'
            // }
    
            this.activated = this.activated === 'activated' ? '': 'activated'
        }
    }
    
    • style对象绑定
    <div id="app">
        <div @click='handleDivClick'
            :style='[vueStyle, {background: "yellow"}]'>
            Hello World!
        </div>
    </div>
    ...
    data: {
        vueStyle: {
            color: 'red'
        }
    },
    methods: {
        handleDivClick: function() {
            this.vueStyle.color = this.vueStyle.color === 'red' ? 'black': 'red'
        }
    }
    
  • 条件渲染

    • v-if … v-else-if … v-else
      1. 必须挨在一起,中间有其他标签无法识别
      2. 如果包裹的是input标签,需要加入key属性来加以区分
    • v-show:根据条件展示元素的选项,用法同v-if
      • 不管判定值是否为真都会渲染,当判定值为false时,display: none;
    • v-if与v-show区别:
      • v-if 是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
      • v-show 不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
      • v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
    	<div id="app">
            <div v-if='show === "a"'>name:<input k='a'/></div>
            <div v-else-if='show === "b"'>mobile:<input k/></div>
            <div v-else>email:<input></div>
            <div v-show='isshow'>{{message}}</div>
        </div>
        <script>
            var vm = new Vue({
                el: '#app',
                data: {
                    show: 'a',
                    isshow: true,
                    message: 'get it',
                }
            })
        </script>
    
  • 列表渲染v-for

    1. 列表在页面渲染后修改特定元素无法同步到页面中;
    2. 字典在渲染以后修改特定属性可以同步到页面中,但是增加key/value无法同步到页面中;
    3. 重新赋值列表/字典可以同步到页面;
    4. 使用列表的变异方法修改元素可以同步到页面,如下例使用vm.nameList.splice(1,1,'haha')
      • push() 往列表中加入元素
      • pop() 删除最后一个元素
      • shift() 删除第一个元素
      • unshift() 返回元素个数
      • splice(n, m, ‘xxx’) 指定从第n个元素开始删除m个元素,替换值xxx
      • sort() 对列表进行排序
      • reverse() 将列表倒叙排列
    5. set修改列表元素并同步到页面中
      • Vue.set(object, key, value)
      • object. s e t ( o b j e c t , k e y , v a l u e ) 举 栗 : V u e . s e t ( v m . n a m e L i s t , 0 , ′ f o n e 93 3 ′ ) v m . set(object, key, value) 举栗: Vue.set(vm.nameList, 0, 'fone933') vm. set(object,key,value)Vue.set(vm.nameList,0,fone933)vm.set(vm.infoDict, ‘age’, 23)
<div id="app">
    <template v-for='item, index in nameList'>
        <li>{{index}}. {{item}}</li>
    </template>
    <ol>
        <li v-for='(value, key, index) in infoDict'>{{key}}=={{value}} ({{index}})</li>
    </ol>
</div>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            nameList: ['fone', 'alex', 'rain', 'jack'],
            infoDict: {
                'name': 'fone',
                'age': 123,
                'email': 'fone@z.com'
            }
        }
    })
</script>
  • 高阶 & 拓展
    1. is指示模板,对于h5标准嵌套标签,若不符合嵌套规则会出现渲染错乱的情况,如ul > li是标准。
      若下栗中tbody标签中直接使用row子组件标签会出现渲染错乱。

    2. 子组件中定义data必须以函数的形式

    • 1 2知识点汇总饭粒
    <div id="table">
        <table>
            <tbody>
                <tr is='row'></tr>
                <tr is='row'></tr>
            </tbody>
        </table>
    </div>
    <script>
        Vue.component('row', {
                data: function() {
                    return {
                        contend: 'This is one row.'
                    }
                },
                template: '<tr><td>{{contend}}</td></tr>'
            })
        var app = new Vue({
            el: '#table'
        })
    </script>
    
    1. ref使用
      (在Vue实例中使用this.$refs.引用名.引用属性
    • 饭粒:累加求和
    <div id="app">
        <counter ref='one' @change='handleChange'></counter>
        <counter ref='two' @change='handleChange'></counter>
        <div>{{sum}}</div>
    </div>
    <script>
        Vue.component('counter', {
            template: '<div @click="handleClick">{{number}}</div>',
            data: function() {
                return {
                    number: 0
                }
            },
            methods: {
                handleClick: function() {
                    this.number ++,
                    this.$emit('change')
                }
            }
        })
    
        var vm = new Vue({
            el: '#app',
            data: {
                sum: 0
            },
            methods: {
                handleChange: function() {
                    this.sum = this.$refs.one.number + this.$refs.two.number
                }
            }
        })
    </script>
    
    1. 组件传值

      • 父组件通过属性的形式向子组件传递,子组件中用props接收(属性不会渲染到页面中)
      • 单向数据流:子组件不能修改父组件传递过来的数据,若要改就重新定义一个变量来接收传递值,修改变量即可
      • 父传子的数据为非字符就要用v-bind的方式绑定,如下栗 :count=“1” 传递的是数字
      • 子组件通过事件触发的形式向父组件传递,如$emit
      • 给子组件绑定Vue实例的事件使用.native
      <div id="app">
          <counter :count="1" @change='handleChange'></counter>
          <counter :count="2" @change='handleChange'></counter>
          <div @click.native='onClick'>{{sum}}</div>
      </div>
      <script>
          var counter = {
              props: ['count'],
              data: function() {
                  return {
                      number: this.count
                  }
              },
              template: '<div @click="handleClick">{{number}}</div>',
              methods: {
                  handleClick: function() {
                      this.number += 3,
                      this.$emit('change', 3)
                  }
              }
          }
      
          var vm = new Vue({
              el: '#app',
              components: {
                  counter: counter,
              },
              data: {
                  sum: 3
              },
              methods: {
                  handleChange: function(step) {
                      this.sum += step
                  },
                  onClick: function() {
                      alert('click...')
                  }
              }
          })
      </script>
      
    2. props传值验证

      1. 类型:type,String、Number等,传入多个类型表示或关系(下栗注释部分)
      2. 默认值:default
      3. 是否必传:required
      4. 验证函数:validator,传值以参数传入
      <div id="app">
          <child msg='ffffff'></child>
      </div>
      <script>
          Vue.component('child', {
              props: {
                  // msg: [String, Number],
                  msg: {
                      type: String,
                      default: '666999',
                      required: true,
                      validator: function(value) {
                          return (value.length > 5)
                      }
                  }
              },
              template: '<div>{{msg}}</div>'
          })
          var vm = new Vue({
              el: "#app",
          })
      </script>
      
    3. 非父子组件传值: 定义Vue.prototype.bus,用钩子函数mounted接收子组件触发的事件

      <div id="app">
          <baba msg='woshiniba'></baba>
          <baba msg='woshimama'></baba>
      </div>
      <script>
          Vue.prototype.bus = new Vue()
      
          Vue.component('baba', {
              props: {
                  msg: String
              },
              data: function() {
                  return {
                      myData: this.msg
                  }
              },
              template: '<div @click="handleClick">{{myData}}</div>',
              methods: {
                  handleClick: function() {
                      this.bus.$emit('change', this.myData)
                  }
              },
              mounted: function() {
                  var _this = this
                  this.bus.$on('change', function(val) {
                      _this.myData = val
                  })
              }
          })
          var vm = new Vue({
              el: '#app',
          })
      </script>
      
    4. slot插槽(自定义组件中内容即为插槽)
      · 饭粒1

      <div id="app">
          <haha>
              <h1 slot='header'>header</h1>
              <h6 slot='footer'>footer</h6>
          </haha>
      </div>
      <script>
          Vue.component('haha', {
              template: `<div>
                          <slot name='header'></slot>
                          <p>content</p>
                          <slot name='footer'></slot>
                         </div>`
          })
          var vm = new Vue({
              el: '#app',
          })
      </script>
      

      · 饭粒2:子组件做循环或DOM结构需要从外部传入(插槽必须使用template,并使用slot-scope属性接收传递值)

      <div id="app">
          <tag>
              <template slot-scope='props'>
                  <h3>{{props.item}}</h3>
              </template>
          </tag>
      </div>
      <script>
          Vue.component('tag', {
              data: function() {
                  return {
                      list: [1, 2, 3, 4]
                  }
              },
              template: `<div><slot v-for="item in list" :item=item></slot></div>`
          })
          var vm = new Vue({
              el: '#app'
          })
      </script>
      
    5. 拓展

      • 动态组件:component,下栗给动态组件绑定数据,数据值即为显示的组件
      • v-once:将组件放入内存,降低渲染页面消耗的性能
      • 饭粒:点击change按钮改变组件
      <div id="app">
          <component :is='current'></component>
          <!-- <tag-one v-if='current === "tag-one"'></tag-one>
          <tag-two v-if='current === "tag-two"'></tag-two> -->
          <button @click='handleClick'>change</button>
      </div>
      <script>
          Vue.component('tag-one', {
              template: '<div  v-once>Child One</div>'
          })
          Vue.component('tag-two', {
              template: '<div  v-once>I am you father!</div>'
          })
          var vm = new Vue({
              el: '#app',
              data: {
                  current: 'tag-one'
              },
              methods: {
                  handleClick: function() {
                      this.current = this.current === 'tag-one' ? 'tag-two' : 'tag-one'
                  }
              }
          })
      </script>
      
  • Vue动画
    1. CSS动画
      · 纯transition动画

      <!DOCTYPE html>
      <html lang="zh-CN">
          <head>
              <title>CSS动画</title>
              <meta charset="UTF-8">
              <meta name="viewport" content="width=device-width, initial-scale=1">
              <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
              <style>
                  .fone-enter, .fone-leave-to {
                      opacity: 0;
                  }
                  .fone-enter-active, .fone-leave-active {
                      transition: opacity 3s;
                  }
              </style>
          </head>
          <body>
              <div id="app">
                  <button @click='handleClick'>{{btm}}</button>
                  <transition name='fone'>
                      <div v-if='isShow'>{{msg}}</div>
                  </transition>
              </div>
              <script>
                  var vm = new Vue({
                      el: "#app",
                      data: {
                          btm: '消失',
                          msg: 'Hello World!!!',
                          isShow: true
                      },
                      methods: {
                          handleClick: function() {
                              this.isShow = ! this.isShow,
                              this.btm = this.btm === '出现' ? '消失' : '出现'
                          }
                      }
                  })
              </script>
          </body>
      </html>
      
      • animate组件 keyframes animate

      • keyframes与transition

        • 入场动画 appear appear-active-class=’’
        • keyframes与transition同时加入 v-enter v-leave-to v-enter-active v-leave-active
        • 动画优先级 type=’’
        • 动画时长 :duration="{enter: 5000, leave: 6000} 单位ms"
        <!DOCTYPE html>
        <html lang="zh-CN">
            <head>
                <title>CSS动画</title>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1">
                <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>
                <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.0/animate.min.css">
                <style>
                    #app {
                        text-align: center
                    }
                    .fone-enter, .fone-leave-to {
                        opacity: 0;
                    }
                    .fone-enter-active, .fone-leave-active {
                        transition: opacity 3s;
                    }
                    /* @keyframes bounce-in {
                        0% {
                            transform: scale(0);
                        }
                        50% {
                            transform: scale(2);
                        }
                        100% {
                            transform: scale(1);
                        }
                    }
                    .enter {
                        transform-origin: center;
                        animation: bounce-in 2s;
                    }
                    .leave {
                        transform-origin: center;
                        animation: bounce-in 2s reverse;
                    } */
                </style>
            </head>
            <body>
                <div id="app">
                    <button @click='handleClick'>{{btm}}</button>
                    <transition name='fone'
                                appear
                                type='keyframes'
                                enter-active-class='animated swing fone-enter-active'
                                leave-active-class='animated tada fone-leave-active'
                                appear-active-class='animated bounceInUp'>
                        <div v-if='isShow'>{{msg}}</div>
                    </transition>
                </div>
                <script>
                    var vm = new Vue({
                        el: "#app",
                        data: {
                            btm: '消失',
                            msg: 'Hello World!!!',
                            isShow: true
                        },
                        methods: {
                            handleClick: function() {
                                this.isShow = ! this.isShow,
                                this.btm = this.btm === '出现' ? '消失' : '出现'
                            }
                        }
                    })
                </script>
            </body>
        </html>
        
    2. js动画

      • 钩子:@before-enter=’’
        @enter=’’
        @after-enter=’’ 要在enter函数中执行done才会到这个钩子
        @before-leave=’’
        @leave=’’
        @after-leave=’’
      <div id="app">
          <button @click='handleClick'>biu</button>
          <transition
              @before-enter='handleBeforeEnter'
              @enter='handleEnter'
              @after-enter='handleAfterEnter'
              @before-leave='handleBeforeLeave'
              @leave='handleLeave'
              @after-leave='handleAfterLeave'
          >
              <div v-show='show'>我来也!</div>
          </transition>
      </div>
      <script>
          var vm = new Vue({
              el: '#app',
              data: {
                  show: true
              },
              methods: {
                  handleClick: function() {
                      this.show = ! this.show
                  },
                  handleBeforeEnter: function(el) {
                      el.style.color = 'red'
                  },
                  handleEnter: function(el, done) {
                      setTimeout(() => {
                          el.style.color = 'green'
                      }, 2000),
                      setTimeout(() => {
                          done()
                      }, 3000)
                  },
                  handleAfterEnter: function(el) {
                      el.style.color = 'yellow'
                  },
                  handleBeforeLeave: function(el) {
                      el.style.color = 'blue'
                  },
                  handleLeave: function(el, done) {
                      setTimeout(() => {
                          el.style.color = 'pink'
                      }, 2000),
                      setTimeout(() => {
                          done()
                      }, 3000)
                  },
                  handleAfterLeave: function(el) {
                      el.style.color = 'origon'
                  }
              }
          })
      </script>
      
      • verocity.js动画 verocity
        <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
      handleEnter: function(el, done) {
          Velocity(el, {opacity: 1}, {duration: 2000, complete: done})
      }
      
      • 多个元素的动态切换transition
      <style>
          .v-enter, .v-leave-to {
              opacity: 0;
          }
          .v-enter-active, .v-leave-active {
              transition: opacity 2s;
          }
      </style>
      ...
      <div id="app">
          <button @click='handleClick'>biu</button>
          <transition mode='out-in'>
              <div v-if='show' key='enter'>我来也!</div>
              <div v-else key='leave'>你走吧!</div>
          </transition>
      </div>
      <script>
          var vm = new Vue({
              el: '#app',
              data: {
                  show: true
              },
              methods: {
                  handleClick: function() {
                      this.show = ! this.show
                  },
              }
          })
      </script>
      
      • 多个组件的动态切换 component
      <!-- 与上栗style相同 -->
      <div id="app">
          <button @click='handleClick'>biu</button>
          <transition mode='out-in'>
              <component :is='type'></component>
          </transition>
      </div>
      <script>
          Vue.component('baba', {
              template: '<div>我是你爸!</div>'
          })
          Vue.component('mama', {
              template: '<div>我是麻麻!</div>'
          })
          var vm = new Vue({
              el: '#app',
              data: {
                  type: 'baba'
              },
              methods: {
                  handleClick: function() {
                      this.type = this.type === 'baba' ? 'mama' : 'baba'
                  },
              }
          })
      </script>
      
      • 列表过渡 transition-group 列表展开后相当于多个transition标签
      <!-- 与上栗style相同 -->
      <div id="app">
          <button @click='handleClick'>biu</button>
          <transition-group mode='out-in'>
              <div v-for='item in item_list' :key='item.id'>{{item.msg}}</div>
          </transition-group>
      </div>
      <script>
          var vm = new Vue({
              el: '#app',
              data: {
                  count: 0,
                  item_list: []
              },
              methods: {
                  handleClick: function() {
                      this.item_list.push({
                          id: this.count++,
                          msg: 'what???'
                      });
                  },
              }
          })
      </script>
      
      • 将动画封装到组件中 transition slot @before-enter
      <div id="app">
          <button @click='handleClick'>biu</button>
          <fade :show='show'>
              <div>你大爷!</div>
          </fade>
          
      </div>
      <script>
          Vue.component("fade", {
              props: ['show'],
              template: `<transition @before-enter='handleBeforeEnter' @enter='handleEnter' @after-enter='handleAfterEnter'>
                          <slot v-if='show'></slot>
                         </transition>`,
              methods: {
                  handleBeforeEnter: function(el) {
                      el.style.background = 'aqua'
                  },
                  handleEnter: function(el, done) {
                      setTimeout(() => {
                          el.style.color = 'blue',
                          done()
                      }, 2000)
                  },
                  handleAfterEnter: function(el) {
                      el.style.background = 'yellow'
                  }
              }
          })
          var vm = new Vue({
              el: '#app',
              data: {
                  show: true
              },
              methods: {
                  handleClick: function() {
                      this.show = ! this.show
                  }
              }
          })
      </script>
      
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值