vue入门到精通

一. Vue基础

邂逅Vue.js

初识Vue.js

Vue.js官网: https://www.vuejs.org.
Vue是一个渐进式 的框架

渐进式意味着你可以将Vue作为你应用的一部分嵌套其中
Vue的核心库以及其生态系统
Core + Vue-router + Vuex
Vue特点和Web开发常见高级功能

  1. 解耦视图和数据
  2. 可复用的组件
  3. 前端路由技术
  4. 状态管理
  5. 虚拟DOM

Vue安装方式

一、直接用 <script> 引入
直接下载并用 <script> 标签引入,Vue 会被注册为一个全局变量。

在这里插入图片描述
【注】
开发环境版本, 包含了帮助的命令行警告
生产环境版本, 优化了尺寸和速度

二、直接CDN引入
对于制作原型或学习,你可以这样使用最新版本:

<srcipt src='https://cdn.jsdeliver.net/npm/vue/dist/vue.js'></script>

对于生产环境,我们推荐链接到一个明确的版本号和构建文件,以避免新版本造成的不可预期的破坏:

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>

如果你使用原生 ES Modules,这里也有一个兼容 ES Module 的构建文件:

<script type="module">
  import Vue from 'https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.esm.browser.js'
</script>

你可以在 https://cdn.jsdelivr.net/npm/vue/.浏览 NPM 包的源代码。

Vue 也可以在 unpkg 和 cdnjs 上获取 (cdnjs 的版本更新可能略滞后)。

请确认了解不同构建版本并在你发布的站点中使用生产环境版本,把 vue.js 换成 vue.min.js。这是一个更小的构建,可以带来比开发环境下更快的速度体验。

三、NPM安装
在用 Vue 构建大型应用时推荐使用 NPM 安装。NPM 能很好地和诸如 webpack 或 Browserify 模块打包器配合使用。同时 Vue 也提供配套工具来开发单文件组件。

通过webpack和CLI的使用
安装脚手架npm i -g vue vue-cli
【注】需要node.js npm

二. Vue基础语法

vue基本框架搭建

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="../js/vue.js"></script>
  </head>
  <body>
    <div id="app">
      {{name1}}
      <li>{{age}}</li>
      <li>{{sex}}</li>
    </div>
    <script>
      const pos = new Vue({
        el: "#app",
        data: {
          name1: "小明",
          age: 20,
          sex: "男",
        },
      });
    </script>
  </body>
</html>

在这里插入图片描述

1.引入vue.js后,给我们提供了一个构造函数 Vue

2.在js中,new Vue()

3.new Vue() 后会返回一个vue实例对象,我们用变量接着它

4.const pos = new Vue()

5.传入一个配置对象{} — 如const pos = new Vue({})

el

  • 类型:字符串
  • 全称:element(元素)
  • 作用:配置控制的元素,表示Vue要控制的区域,值为css id选择器(挂载到dom里)
   <div id="app">
    </div>
   <script>
      const pos = new Vue({
        el: "#app",
        )}
    </script>

$mount

  • 作用和el一致,都是配置控制的元素,使用哪个都可以,二选一
new Vue({
  render: (h) => h(App),
}).$mount("#app");
  • 问:和el有什么不同?
  • 答:本质上没什么不同,$mount为手动挂载,在项目中有时要进行延迟挂载,比如有时要在挂载之前进行一些其他的操作,比如判断等等

data

  • 类型:对象

  • 作用:存放要用到的数据,数据为响应式的

const pos = new Vue({
        el: "#app",
        data: {
          name1: "小明",
          age: 20,
          sex: "男",
        },
      });

插值表达式

  • 使用方法: {{ }}

  • 作用:可以将vue中的数据填在插值表达式中,如:

  <body>
    <div id="app">
      {{name1}}
      <li>{{age}}</li>
      <li>{{sex}}</li>
    </div>
    <script>
      const pos = new Vue({
        el: "#app",
        data: {
          name1: "小明",
          age: 20,
          sex: "男",
        },
      });
    </script>
  </body>
</html>
  • 除了填写data之外,还可以直接填写数据值(数字、字符串、布尔值、undefined、null、数组、对象),如:
  <div id="app">
    {{ 5201314 }}
    {{ '婀娜多姿、亭亭玉立' }}
    {{ true }}
    {{ ['小红', '小刘', '小宝'] }}
    {{ {name: '小红', age: 80, height: '140cm', weight: '100kg'} }}
  </div>

  • 注意:在插值表达式中直接书写对象类型值时,不要将三个{}连在一起,这样会报错,如:
  <div id="app">
    <!-- 这样可是不行滴 -->
    {{{name: '小明', age: 80, height: '140cm', weight: '100kg'}}} 
  </div>
  • 还可在插值表达式中写表达式,如:
 <div id="app">
   <!-- 运算表达式 -->
   {{ 'you' + 'me' }}
   {{ 10 - 5 }}
   {{ 100 * 7 }}
   {{ 1000 / 12 }}
   <!-- 逻辑表达式 -->
   {{ liu || li }}
   {{ deng && liu }}
   {{ !wang }}
   <!-- 三元表达式 -->
   {{ 1 + 1 === 3 ? '小明' : '人' }}
   <!-- 函数调用也是表达式,也可以使用,这个以后再学哈... -->
 </div>

vue的响应式

  • 数据变化,页面就会重新渲染
  • 问:为什么data会直接出现在vm实例对象中咧?

答:当创建vue实例时,vue会将data中的成员代理给vue实例,目的是为了实现响应式,监控数据变化,执行某个监听函数(怎么实现的?想一想,提示:Object.defineProperty,试着实现一下)

  • 问:实例中除了data数据外,其他东西是啥子?

答:为了防止名称冲突。因为会将data中数据代理给vue,假如说我们自己写的data名称和vue中自带的属性冲突了,那么就会覆盖vue内部的属性,所以vue会把自己内部的属性成员名称前加上 或 , 如 果 加 上 的 是 或_,如果加上的是 ,代表是我们可以使用的,如果加上的是_,是vue自己内部使用的方法或属性,我们不需要调用

  • 更改的数据必须是存在的数据,否则不能重新渲染页面,因为他监听不到,如:
  <!-- 即使更改了数据,也不会重新渲染页面 -->
  <div id="app">
    {{ message.wife }} 
  </div>
<script>
  const vm = new Vue({
    el: '#app',
    data: {
      message: {
        name: '邓旭明', 
        age: 80, 
        height: '140cm', 
        weight: '100kg'
      }
    }
  })
  vm.mrDeng.wife = 'liu';
</script>
  • 更改数据后,页面会立刻重新渲染吗?

vue更新DOM的操作是异步执行的,只要侦听到数据变化,将开启一个异步队列,如果一个数据被多次变更,那么只会被推入到队列中一次,这样可以避免不必要的计算和DOM操作。

$el

  • 值为被Vue控制的元素(或者说,Vue挂载的元素)

vm.$nextTick & Vue.nextTick

如何在更改数据后,看到渲染后的页面上的值?

答:利用vm. n e x t T i c k 或 V u e . n e x t T i c k , 在 页 面 重 新 渲 染 , D O M 更 新 后 , 会 立 刻 执 行 v m . nextTick或 Vue.nextTick,在页面重新渲染,DOM更新后,会立刻执行vm. nextTickVue.nextTickDOMvm.nextTick

<div id="app">{{ name }}</div>


<script>
const vm = new Vue({
  el: '#app',
  data: {
    name: '小明'
  }
})
vm.name= '小美';
console.log(vm.msg); // 小美,此时数据已更改
// 1. 使用vm.$nextTick
vm.$nextTick(() => {
  console.log(vm.$el.innerHTML); // 小美
})
// 2. 使用Vue.nextTick
Vue.nextTick(() => {
  console.log(vm.$el.innerHTML); // 小美
})
</script>

  • vm.nextTick和Vue.nextTick还可以作为Promise使用
<div id="app">{{ msg }}</div>
<script>
const vm = new Vue({
  el: '#app',
  data: {
    msg: '杉杉'
  }
})
vm.msg = '杉杉超美的';
// 1. 使用vm.$nextTick
vm.$nextTick().then(() => {
  console.log(vm.$el.innerHTML); // 杉杉超美的
})
// 2. 使用Vue.nextTick
Vue.nextTick().then(() => {
  console.log(vm.$el.innerHTML); // 杉杉超美的
})
</script>

  • vm.$nextTick 和 Vue.nextTick的区别?

Vue.nextTick内部函数的this指向window

vm.$nextTick内部函数的this指向Vue实例对象

  • 好奇nextTick是怎么实现的吗?

  • 异步任务分为宏任务(macro)和微任务(micro)

  • 宏任务比较慢(如setTimeout等),微任务比较快(如Promise.then()等)

  • 微任务在前,宏任务在后(eventloop,事件环)

  // 控制台打印顺序:promise > timeout
  setTimeout(() => {
    console.log('timeout');
  }, 0)  
  Promise.resolve().then(() => {
    console.log('promise');
  })

  • 在nextTick的实现源码中,会先判断是否支持微任务,不支持后,才会执行宏任务
  if(typeof Promise !== 'undefined') {
    // 微任务
    // 首先看一下浏览器中有没有promise
    // 因为IE浏览器中不能执行Promise
    const p = Promise.resolve();

  } else if(typeof MutationObserver !== 'undefined') {
    // 微任务
    // 突变观察
    // 监听文档中文字的变化,如果文字有变化,就会执行回调
    // vue的具体做法是:创建一个假节点,然后让这个假节点稍微改动一下,就会执行对应的函数
  } else if(typeof setImmediate !== 'undefined') {
    // 宏任务
    // 只在IE下有
  } else {
    // 宏任务
    // 如果上面都不能执行,那么则会调用setTimeout
  }


  • 除了未被声明过和未被渲染的数据外,还有什么数据更改后不会渲染页面?
  1. 利用索引直接设置一个数组项时:
<!-- 即使向数组中添加了第4项,数组仍然显示3项 -->
<div id="app">{{ list }}</div>


<script>
const vm = new Vue({
  el: '#app'
  data: {
    dengFamily: ['小明', '小刘', '小宝']
  }
})
vm.dengFamily[3] = '铁锤妹妹'; // 不是响应式的

</script>
  1. 修改数组的长度时:
<!-- 更改了数组长度后,数组仍然显示1项 -->
<div id="app">{{ list }}</div>

<script>
const vm = new Vue({
  el: '#app'
  data: {
    dengWife: ['小刘']
  }
})
vm.dengWife.length = 0; // 不是响应式的

</script>
  1. 添加或删除对象:
<!-- 身高还是那个身高,媳妇也只有一个,不要痴心妄想 -->
<div id="app">{{ deng }}</div>

<script>
const vm = new Vue({
  el: '#app'
  data: {
    deng: {
      wife: '小刘',
      son: '小宝',
      weight: '100kg',
      height: '140cm',
      age: 60
    }
  }
})
vm.deng.secondWife = '铁锤妹妹'; // 不是响应式的
delete vm.deng.height; // 不是响应式的
</script>

  1. 要如何响应式的更新数组和对象?

更改数组:
利用数组变异方法:
push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度、
pop()方法可以将数组最后一位元素删除
shiftshift()方法可以将数组第一位元素删除
unshift()方法可以在数组开头添加任意数量的元素
splice() 有三个参数,第一个是想要删除的元素的下标(必选),第二个是想要删除的个数(必选),第三个是删除后原位置想要替换的值
sort() 是数组按照字符编码默认从小到大排序,成功返回排序后的数组
reverse() 将数组倒序,成功返回倒序的数组

更改对象:
1.利用vm. s e t / V u e . s e t 实 例 方 法 : v m . set/Vue.set实例方法: vm. set/Vue.set:vm.set是Vue.set的别名
使用方法:Vue.set(object, propertyName, value),也就是这个意思:Vue.set(要改谁,改它的什
么,改成啥)
2.利用vm. d e l e t e / V u e . d e l e t e t 删 除 数 组 中 的 某 一 项 : v m . delete/Vue.deletet删除数组中的某一项:vm. delete/Vue.deletet:vm.delete是Vue.delete的别名
使用方法:Vue.delete(object, target),也就是这个意思:Vue.delete(要删除谁的值,删除哪个)

一. Vue基础

Vue相关指令

  • 具有特殊含义、拥有特殊功能的特性
  • 指令带有v-前缀,表示它们是Vue提供的特殊特性
  • 指令可以直接使用data中的数据

v-pre

  • 跳过这个元素和它的子元素的编译过程。可以用来显示原始 Mustache 标签。跳过大量没有指令的节点会加快编译。
<!-- 不会被编译 -->
<span v-pre>{{ msg }}</span>

v-cloak

  • 这个指令保持在元素上直到关联实例结束编译
  • v-cloak 在vue解析之前有一个属性v-cloak,解析之后消失
[v-cloak] {
  display: none;
}

<div v-cloak>
  {{ message }}
</div>
  • 和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Mustache(也就是{{双花括号}} ) 标签直到实例准备完毕

v-once

  • 只渲染元素一次。随后的重新渲染,元素及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能
  • v-once {{}}中内容一次性显示

v-text

<span v-text="msg"></span>
<!-- 和下面的一样 -->
<span>{{msg}}</span>
  • v-text替换元素中所有的文本,Mustache只替换自己,不清空元素内容
<!-- 渲染为:<span>杉杉最美</span> -->
<span v-text="msg">----</span>
<!-- 渲染为:<span>----杉杉最美----</span> -->
<span>----{{msg}}----</span>


  • v-text 优先级高于 {{ }}

v-html

  • 更新元素的innerHTML

  • 注意:内容按普通 HTML 插入,不会作为 Vue 模板进行编译

  • 在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击。只在可信内容上使用 v-html,永不用在用户提交的内容上。

    <button>点击</button>
    <div id="app">
      <div v-html="msg"></div>
    </div>

    <script>
      const vm = new Vue({
        el: "#app",
        data: {
          msg: "hello world",
        },
      });

      const oButton = document.getElementsByTagName("button")[0];
      let msg = "<p>这是一个p</p>";
      oButton.onclick = function () {
        vm.msg = msg;
      };
    </script>

效果图
在这里插入图片描述

条件渲染

v-if

  • 用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 true 的时候被渲染。

v-else

  • 为 v-if 或者 v-else-if 添加“else 块”。
  • 注意:前一兄弟元素必须有 v-if 或 v-else-if
<div v-if="Math.random() > 0.5">
  小明
</div>
<div v-else>
  小红
</div>

v-else-if

  • 表示 v-if 的 “else if 块”。可以链式调用。

  • 注意:前一兄弟元素必须有 v-if 或 v-else-if

<div v-if="type === 'A'">
  A
</div>
<div v-else-if="type === 'B'">
  B
</div>
<div v-else-if="type === 'C'">
  C
</div>
<div v-else>
  Not A/B/C
</div>


v-show

  • 根据表达式之真假值,切换元素的 display CSS 属性。
  • 也就是判断该内容是否显示

v-if与v-show的区别

v-if 是惰性的,如果在初始渲染时条件为假,则什么也不做,直到条件第一次变为真时,才会开始渲染条件块。v-show则不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
v-if 有更高的切换开销,v-show 有更高的初始渲染开销,如果需要非常频繁地切换,则使用 v-show 较好,如果在运行时条件很少改变,则使用 v-if 较好
v-show不支持< template>元素
v-show不支持v-else/v-else-if

v-bind 指令

  • v-bind用于绑定一个或多个属性值
  • 语法糖写法:属性=“值”
<!-- 绑定一个属性 -->
<img v-bind:src="imageSrc">

<!-- 动态特性名 (2.6.0+) -->
<button v-bind:[key]="value"></button>

<!-- 缩写 -->
<img :src="imageSrc">

<!-- 动态特性名缩写 (2.6.0+) -->
<button :[key]="value"></button>

<!-- 内联字符串拼接 -->
<img :src="'/path/to/images/' + fileName">


  • 没有参数时,可以绑定到一个包含键值对的对象。注意此时 class 和 style 绑定不支持数组和对象。
<!-- 绑定一个有属性的对象 -->
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>

  • 绑定class
  • 对象语法
<div v-bind:class="{ red: isRed }"></div>

上面的语法表示 red 这个 class 存在与否将取决于数据属性 isRed 的 真假。

  • 数组语法
    我们可以把一个数组传给 v-bind:class,以应用一个 class 列表
<div v-bind:class="[classA, classB]"></div>
  • 在数组语法总可以使用三元表达式来切换class
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>

class选取哪一个,取决与isActive 的 真假。

  • v-bind:class 可以与普通 class 共存
  <div v-bind:class="classA" class="red">

  • 绑定style
  • 使用对象语法
    看着比较像CSS,但其实是一个JavaScript对象
    CSS属性名可以用驼峰式(camelCase)或者短横线分隔(kebab-case)来命名
    但是使用短横线分隔时,要用引号括起来
<div v-bind:style="{ fontSize: size + 'px' }"></div>

data: {
  size: 30
}

也可以直接绑定一个样式对象,这样模板会更清晰:

<div v-bind:style="styleObject"></div>

data: {
  styleObject: {
    fontSize: '13px'
  }
}

  • 使用数组语法

数组语法可以将多个样式对象应用到同一个元素

<div v-bind:style="[styleObjectA, styleObjectB]"></div>

[注]加单引号为属性值,不加解析为变量

  • 修饰符:
    修饰符 (modifier) 是以英文句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。
  • .camel

由于绑定特性时,会将大写字母转换为小写字母

<svg :viewBox='viewBox'></svg>
<script>
const vm = new Vue({
    el: "#app",
    data: {
        viewBox:'0 0 100 100'
    }
})
</script>

在这里插入图片描述

<svg :view-box.camel='viewBox'></svg>


在这里插入图片描述

  • .prop

被用于绑定 DOM 属性 (property)

<div v-bind:text-content.prop="text"></div>

<script>
const vm = new Vue({
    el: "#app",
    data: {
        text:'智者不如爱河'
    }
})
</script>

在这里插入图片描述

  • .sync

讲解组件时再说

v-on指令

  • v-on 指令可以监听 DOM 事件,并在触发时运行一些 JavaScript 代码
  • 事件类型由参数指定
<div id="app">
  <button v-on:click="counter += 1">点击加 1</button>
  <p>按钮被点击了 {{ counter }} 次</p>
</div>
const vm = new Vue({
  el: 'app',
  data: {
    counter: 0
  }
})


  • 但是很多事件处理逻辑是非常复杂的,所以直接把 JavaScript 代码写在 v-on 指令中是不可行的。所以 v-on 还可以接收一个需要调用的方法名称。
<div id="app">
  <!-- `addCounter` 是在下面定义的方法名 -->
  <button v-on:click="addCounter">点击加 1</button>
  <p>按钮被点击了 {{ counter }} 次</p>
</div>

const vm = new Vue({
  el: '#app',
  data: {
    counter: 0
  },
  // 在 methods 对象中定义方法
  methods: {
    addCounter(e) {
      // this 在方法里指向当前 Vue 实例
      this.counter += 1// e 是原生 DOM 事件
      console.log(e.target)}
  }
})


  • 可以绑定动态事件,Vue版本需要2.6.0+
<div v-on:[event]="handleClick">点击,弹出1</div>  

const vm = new Vue({
  el: '#app',
  data: {
    event: 'click'
  },
  methods: {
    handleClick () {
      alert(1);
    }
  }
})
  • v-on指令简写:@

为什么在 HTML 中监听事件?

  • 扫一眼 HTML 模板便能轻松定位在 JavaScript 代码里对应的方法。
  • 因为你无须在 JavaScript 里手动绑定事件,你的 ViewModel 代码可以是非常纯粹的逻辑,和 DOM - 完全解耦,更易于测试
  • 当一个 ViewModel 被销毁时,所有的事件处理器都会自动被删除。你无须担心如何清理它们

v-on指令的修饰符

.stop
  • 调用 .stop,阻止事件冒泡
<!-- 此时只弹出button -->
<div id="app">
  <div @click="alert('div')">
    <button @click.stop="alert('button')">点击</button>
  </div>
</div>
const vm = new Vue({
  el: '#app',
  methods: {
    alert(str) { alert(str); }
  }
})
.prevent
  • 调用 event.preventDefault(),阻止默认事件
<!-- 点击提交按钮后,页面不会重载 -->
        <form v-on:submit.prevent="onSubmit">
          <input type="submit" />
        </form>
        <!-- 也可以只有修饰符 -->
        <form v-on:submit.prevent>
          <input type="submit" />
        </form>
      </div>
      <!-- 会刷新页面 -->
      <form submit="onSubmit">
        <input type="submit" />
      </form>
    <script>
      const vm = new Vue({
        el: "#app",
        methods: {
          onSubmit() {
            console.log("onSubmit");
          },
        },
      });
    </script>
.capture
  • 事件捕获模式
<!-- 此时先弹出div再弹出button -->
<div id="app">
  <div @click.capture="alert('div')">
    <button @click="alert('button')">点击</button>
  </div>
</div>


.self
  • 只当事件是从侦听器绑定的元素本身触发时才触发回调(也就是说必须是本身触发才会回调)
<!-- 点击button时,只弹出 button -->
<div id="app">
  <div id="app">
    <div :style="{ backgroundColor: 'red' }" 
    @click.self="alert('div')">
      <button @click="alert('button')">点击</button>
    </div>
  </div>
</div>


.once
  • 只触发一次回调

  • 2.1.4新增

.passive
  • 设置 addEventListener 中的 passive 选项
  • 能够提升移动端的性能
  • 2.3.0新增

即使在触发触摸事件时,执行了一个空的函数,也会让页面卡顿。因为浏览器不知道监听器到底会不会阻止默认事件,所以浏览器要等到执行完整个函数后,才能决定是否要滚动页面。passive事件监听器,允许开发者告诉浏览器,监听器不会阻止默认行为,从而浏览器可以放心大胆的滚动页面,这样可以大幅度提升移动端页面的性能,因为据统计只有20%的触摸事件会阻止默认事件。

  • .passive 会告诉浏览器你不想阻止事件的默认行为

注意
使用修饰符时,顺序很重要。相应的代码会以同样的顺序产生。因此,
v-on:click.prevent.self 会阻止所有的点击的默认事件
v-on:click.self.prevent 只会阻止对元素自身点击的默认事件
不要把 .passive 和 .prevent 一起使用,因为 .prevent 将会被忽略,同时浏览器可能会向你展示一个警告。

Vue入门精通》是一本关于Vue.js前端框架的学习指南。本书分为入门、进阶和精通三个部分,帮助读者从零基础开始学习,并逐步掌握Vue.js的核心概念和应用技巧。 在入门部分,书中首先介绍了Vue.js的基本概念,如组件、数据绑定、指令等。读者将学会如何搭建Vue项目、编写Vue组件,并了解Vue的基本语法和工作原理。通过实例演示和练习题,读者可以巩固对Vue基础知识的理解和掌握,为后续的学习打下坚实的基础。 进阶部分则重点讲解了Vue的高级特性和常用技巧。读者将学会如何使用Vue Router进行路由管理、Vuex进行状态管理、以及Vue CLI进行项目构建。此外,该部分还包括了对Vue的响应式原理、性能优化和国际化等方面的深入讲解,帮助读者进一步提升开发能力。 在精通部分,书中通过案例实战、源码解析等方式,深入剖析Vue.js的内部机制和高级用法。读者将学会如何进行自定义指令、混入(mixin)、过滤器(filter)等高级扩展,以及如何优化大型项目的性能和可维护性。此外,书中还介绍了与第三方库、服务端渲染等相关的内容,帮助读者更进一步地掌握和应用Vue.js。 总之,《Vue入门精通》是一本循序渐进、实例丰富的Vue.js学习教材,适合从零开始学习Vue.js的前端开发者。通过系统地学习该书,读者可以逐步掌握Vue.js的核心知识和实际应用技巧,提升自己在前端开发领域的竞争力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值