[[JD_Magi]]Vue.js入门学习

Vue.js入门学习

1、什么是Vue.js

  • Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式JavaScript框架

  • Vue 被设计为可以自底向上逐层应用

  • Vue 的核心库只关注视图层,方便与第三方库或既有项目整合

2、Vue.js的作用

  • 通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件

3、安装

<!--下载文件后引入-->
<script src="文件路径"></script>

<!--在线引入引入-->
	<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

	<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

4、简单了解

4.1、声明式渲染

Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统

helloworld

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
    {{ message }}
</div>
<script>
    var app = new Vue({
        el: '#app',
        data: {
            message: 'hello vue!'
        }
    })
</script>
</body>
</html>

现在数据和 DOM 已经被建立了关联,所有东西都是响应式的,在控制台可以修改app.message的值,就可以看到更新

指令:指令带有前缀 v-,以表示它们是 Vue 提供的特殊属性。,它们会在渲染的 DOM 上应用特殊的响应式行为

鼠标悬停

<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>

<div id="app-2">
    <span v-bind:title = "message">
        鼠标悬停
    </span>
</div>
<script>
    var app2 = new Vue({
        el: '#app-2',
        data: {
            message: "页面加载于"+new Date().toLocaleString()
        }
    })
</script>
</body>
</html>

条件与循环

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app-3">
    <p v-if="seen">现在你看到我了</p>
</div>

<div id="app-4">
    <ol>
        <li v-for="todo in todos">
            {{ todo.text }}
        </li>
    </ol>
</div>
<script>
    var app3 = new Vue({
        el: "#app-3",
        data: {
            seen: true
        }
    })

    var app4 = new Vue({
        el: '#app-4',
        data: {
            todos: [
                {text: '学习JavaScript'},
                {text: '学习vue'},
                {text: '整个牛项目'}
            ]
        }
    })
</script>
</body>
</html>

处理用户输入

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app-5">
    <p>{{message}}</p>
    <button v-on:click="reverseMessage">反转消息</button>
</div>
<script>
    var app5 = new Vue({
        el: '#app-5',
        data:{
            message: 'hello vue!'
        },
        methods:{
            reverseMessage: function () {
                this.message = this.message.split('').reverse().join('')
            }
        }
    })
</script>
</body>
</html>

双向绑定:实现表单输入和应用状态之间的双向绑定

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id = "app-6">
    <p>{{message}}</p>
    <input v-model="message">
</div>
<script>
    var app6 = new Vue({
        el: '#app-6',
        data: {
            message:'hello Vue!'
        }
    })
</script>
</body>
</html>

4.2、组件化应用构建

组件系统:使用小型、独立和通常可复用的组件构建大型应用。几乎任意类型的应用界面都可以抽象为一个组件树。

Component Tree

  • 在 Vue 里,一个组件本质上是一个拥有预定义选项的一个 Vue 实例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app-7">
    <ol>
        <!--
          现在我们为每个 todo-item 提供 todo 对象
          todo 对象是变量,即其内容可以是动态的。
          我们也需要为每个组件提供一个“key”,稍后再
          作详细解释。
        -->
        <todo-item
                v-for="item in groceryList"
                v-bind:todo="item"
                v-bind:key="item.id"
        ></todo-item>
    </ol>
</div>
<script>
    Vue.component('todo-item', {
        props: ['todo'],
        template: '<li>{{ todo.text }}</li>'
    })

    var app7 = new Vue({
        el: '#app-7',
        data: {
            groceryList: [
                { id: 0, text: '蔬菜' },
                { id: 1, text: '奶酪' },
                { id: 2, text: '随便其它什么人吃的东西' }
            ]
        }
    })
</script>
</body>
</html>

5、实例

创建一个Vue实例

  1. 每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的

  2. 一个 Vue 应用由一个通过 new Vue 创建的根 Vue 实例

    var vm = new Vue({
      // 选项
    })
    

数据与方法

当一个 Vue 实例被创建时,它将 data 对象中的所有的 property 加入到 Vue 的响应式系统中。当这些 property 的值发生改变时,视图将会产生“响应”,即匹配更新为新的值。

  • 修改不存在data中的属性是不会修改视图的,如果预先知道需要用的属性可以预先初始化

  • Object.freeze():阻止修改现有的属性

  • $ 符号,用来区分用户定义的属性

    vm.$data === data // => true
    vm.$el === document.getElementById('example') // => true
    
    // $watch 是一个实例方法
    vm.$watch('a', function (newValue, oldValue) {//可以查看修改后的新值和旧值
      // 这个回调将在 `vm.a` 改变后调用
    })
    

生命周期钩子

每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到 DOM 并在数据变化时更新 DOM 等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。

生命周期

Vue 实例生命周期

6、模板语法

  • 所有 Vue.js 的模板都是合法的 HTML,所以能被遵循规范的浏览器和 HTML 解析器解析。
  • 在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。

6.1、插值

文本

<span>Message: {{ msg }}</span><!--将data中的msg插入-->
<span v-once>这个将不会改变: {{ msg }}</span><!--一次性插值-->

html

双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用 v-html

<p>Using mustaches: {{ rawHtml }}</p><!--普通输出,会把html标签当作普通文本输出-->
<p>Using v-html directive: <span v-html="rawHtml"></span></p><!--让html标签能被识别-->

html属性

<div v-bind:id="dynamicId"></div><!--通过v-bind:指令可以实现对html属性的操作-->

js表达式

支持js表达式

{{ number + 1 }}

{{ ok ? 'YES' : 'NO' }}

{{ message.split('').reverse().join('') }}

<div v-bind:id="'list-' + id"></div>

6.2、指令

指令 (Directives) 是带有 v- 前缀的特殊属性

<p v-if="seen">现在你看到我了</p>
<!--
v-if 指令将根据表达式 seen 的值的真假来插入/移除 <p> 元素
-->

参数

一些指令能够接收一个“参数”,在指令名称之后以冒号表示

<a v-bind:href="url">...</a>
<!--
在这里 href 是参数,告知 v-bind 指令将该元素的 href 属性 与表达式 url 的值绑定
-->

<a v-on:click="doSomething">...</a><!--用于监听 DOM 事件-->

动态参数

从 2.6.0 开始,可以用方括号括起来的 JavaScript 表达式作为一个指令的参数

<a v-bind:[attributeName]="url"> ... </a>
<!--
这里的 attributeName 会被作为一个 JavaScript 表达式进行动态求值,求得的值将会作为最终的参数来使用。例如,如果你的 Vue 实例有一个 data property attributeName,其值为 "href",那么这个绑定将等价于 v-bind:href。
-->

对动态参数的值的约束

  • 动态参数预期会求出一个字符串,异常情况下值为 null。这个特殊的 null 值可以被显性地用于移除绑定。任何其它非字符串类型的值都将会触发一个警告。

对动态参数表达式的约束

  • 动态参数表达式有一些语法约束,因为某些字符,如空格和引号,放在 HTML 属性名里是无效的

    <!-- 这会触发一个编译警告 -->
    <a v-bind:['foo' + bar]="value"> ... </a>
    

缩写

v-bind缩写

<!-- 完整语法 -->
<a v-bind:href="url">...</a>

<!-- 缩写 -->
<a :href="url">...</a>

<!-- 动态参数的缩写 (2.6.0+) -->
<a :[key]="url"> ... </a>

v-on缩写

<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>

<!-- 缩写 -->
<a @click="doSomething">...</a>

<!-- 动态参数的缩写 (2.6.0+) -->
<a @[event]="doSomething"> ... </a>

7、计算属性和监听器

7.1、计算属性

基础例子

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="example">
<p>Original message: "{{ message }}"</p>
  <p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
<script>
var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // 计算属性的 getter
    reversedMessage: function () {
      // `this` 指向 vm 实例
      return this.message.split('').reverse().join('')
    }
  }
})
</script>
</body>
</html>
  • 声明了一个计算属性 reversedMessage。提供的函数将用作 property vm.reversedMessage 的 getter 函数
  • Vue 知道 vm.reversedMessage 依赖于 vm.message,因此当 vm.message 发生改变时,所有依赖 vm.reversedMessage 的绑定也会更新
  • 以声明的方式创建了这种依赖关系

计算属性VS方法

  • 计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果
  • 相比之下,每当触发重新渲染时,调用方法将总会再次执行函数

计算属性VS侦听属性

侦听属性:Vue 提供的一种来观察和响应 Vue 实例上的数据变动更通用的方式

当你有一些数据需要随着其它数据变动而变动时,你很容易滥用

通常更好的做法是使用计算属性,而不是命令式的 watch 回调

计算属性的setter

computed: {
  fullName: {
    // getter
    get: function () {
      return this.firstName + ' ' + this.lastName
    },
    // setter
    set: function (newValue) {
      var names = newValue.split(' ')
      this.firstName = names[0]
      this.lastName = names[names.length - 1]
    }
  }
}
//运行 vm.fullName = 'John Doe' 时,setter 会被调用,vm.firstName 和 vm.lastName 也会相应地被更新

7.2、侦听器

虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

8、Class与Style绑定

8.1、绑定HTML Class

对象语法

//单个class
<div v-bind:class="{ active: isActive }"></div>
<script>
data: {
  isActive: true,//通过这个来动态的切换class
}
</script>

//多个class
<div
  class="static"
  v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>
<script>
data: {
  isActive: true,
  hasError: false
}
</script>
  • 可以使用计算属性

数组语法

<div v-bind:class="[activeClass, errorClass]"></div>
<script>
    data: {
      activeClass: 'active',
      errorClass: 'text-danger'
    }
</script>

<!--三元表达式-->
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
  • 中括号里可以使用三元表达式

8.2、绑定内联样式

对象语法

<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

<script>
data: {
  activeColor: 'red',
  fontSize: 30
}
</script>

数组语法

<div v-bind:style="[baseStyles, overridingStyles]"></div>

<script>
	data: {
  baseStyles: {
    color: 'red',
    fontSize: '13px'
  },
  overridingStyles: {
    color: 'red',
    fontSize: '13px'
  }
}
</script>

9、渲染

9.1、条件渲染(if)

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

    <h1 v-if="awesome">Vue is awesome!</h1>
    
  • v-else:v-else 指令用来表示 v-if 的“else 块”

    <h1 v-if="awesome">Vue is awesome!</h1>
    <h1 v-else>Oh no 😢</h1>
    
  • v-else-if:顾名思义,充当 v-if 的“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>
    
  • key 管理可复用的元素:Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。这么做除了使 Vue 变得非常快之外,还有其它一些好处

    <template v-if="loginType === 'username'">
      <label>Username</label>
      <input placeholder="Enter your username">
    </template>
    <template v-else>
      <label>Email</label>
      <input placeholder="Enter your email address">
    </template>
    <!--
    上面的代码中切换 loginType 将不会清除用户已经输入的内容。因为两个模板使用了相同的元素,<input> 不会被替换掉——仅仅是替换了它的 placeholder。
    -->
    
    <template v-if="loginType === 'username'">
      <label>Username</label>
      <input placeholder="Enter your username" key="username-input">
    </template>
    <template v-else>
      <label>Email</label>
      <input placeholder="Enter your email address" key="email-input">
    </template>
    <!--
    Vue 提供了一种方式来表达“这两个元素是完全独立的,不要复用它们”。只需添加一个具有唯一值的 key属性 即可
    -->
    
  • v-show:根据条件展示元素

    <h1 v-show="ok">Hello!</h1>
    
    • v-show 的元素始终会被渲染并保留在 DOM 中
    • v-show 只是简单地切换元素的 CSS property display

9.2、列表渲染(for)

  • 用 v-for 把一个数组对应为一组元素

    <ul id="example-1">
      <li v-for="item in items" :key="item.message">
        {{ item.message }}
      </li>
    </ul>
    <script>
    var example1 = new Vue({
      el: '#example-1',
      data: {
        items: [
          { message: 'Foo' },
          { message: 'Bar' }
        ]
      }
    })
    </script>
    
  • 在 v-for 里使用对象

    <ul id="v-for-object" class="demo">
      <li v-for="value in object">
        {{ value }}
      </li>
    </ul>
    <script>
    new Vue({
      el: '#v-for-object',
      data: {
        object: {
          title: 'How to do lists in Vue',
          author: 'Jane Doe',
          publishedAt: '2016-04-10'
        }
      }
    })
    </script>
    
  • 维护状态

    当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。

    • 适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出
  • 数组更新检测

变更方法

Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

替换数组

变更方法,顾名思义,会变更调用了这些方法的原始数组。相比之下,也有非变更方法,例如 filter()concat()slice()。它们不会变更原始数组,而总是返回一个新数组。当使用非变更方法时,可以用新数组替换旧数组

  • 显示过滤/排序后的结果

    有时,我们想要显示一个数组经过过滤或排序后的版本,而不实际变更或重置原始数据。在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组

    <li v-for="n in evenNumbers">{{ n }}</li>
    <script>
    data: {
      numbers: [ 1, 2, 3, 4, 5 ]
    },
    computed: {
      evenNumbers: function () {
        return this.numbers.filter(function (number) {
          return number % 2 === 0
        })
      }
    }
    </script>
    
  • v-for可以指定循环次数

    <div>
      <span v-for="n in 10">{{ n }} </span>
    </div>
    

10、事件处理

10.1、监听事件

可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id = "example-1">
        <button v-on:click="counter += 1">
            add 1
        </button>
        <p>{{counter}}</p>
    </div>

    <script>
        var expample1 = new Vue({
            el: '#example-1',
            data: {
                counter: 0
            }
        })
    </script>
</body>
</html>

10.2、事件处理方法

v-on 还可以接收一个需要调用的方法名称

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id = "example-2">
        <button v-on:click="greet">greet</button>
    </div>

    <script>
        var example2 = new Vue({
            el: '#example-2',
            data: {
                name:'vue.js'
            },
            methods: {
                greet: function (event) {
                    alert("hello"+this.name+'!');
                    if (event){
                        alert(event.target.tagName);
                    }
                }
            }
        })
    </script>
</body>
</html>

10.3、事件修饰符

Vue.js 为 v-on 提供了事件修饰符,修饰符是由点开头的指令后缀来表示的

  • .stop
  • .prevent
  • .capture
  • .self
  • .once
  • .passive
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

10.4、按键修饰符

在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符

<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
<!--处理函数只会在 $event.key 等于 PageDown 时被调用-->
<input v-on:keyup.page-down="onPageDown">

10.5、系统修饰符

<!-- Alt + C -->
<input v-on:keyup.alt.67="clear">

<!-- Ctrl + Click -->
<div v-on:click.ctrl="doSomething">Do something</div>

<!--.exact修饰符-->
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button v-on:click.ctrl="onClick">A</button>
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button v-on:click.ctrl.exact="onCtrlClick">A</button>
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button v-on:click.exact="onClick">A</button>

<!--鼠标按钮修饰符-->
.left
.right
.middle

11、表单输入绑定

v-model 指令在表单 input、textarea 及select 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。

注意:

v-model 会忽略所有表单元素的 valuecheckedselected attribute 的初始值而总是将 Vue 实例的数据作为数据来源。你应该通过 JavaScript 在组件的 data 选项中声明初始值。

案例

<!--多行文本-->
<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="add multiple lines"></textarea>

<!--复选框-->
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>
...

12、组件

组件是可复用的 Vue 实例,且带有一个名字。我们可以在一个通过 new Vue 创建的 Vue 根实例中,把这个组件作为自定义元素来使用。

基础案例

// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
//data 必须是一个函数  
data: function () {
    return {
      count: 0
    }
  },
  template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})

组件复用

<div id="components-demo">
  <button-counter></button-counter>
  <button-counter></button-counter>
  <button-counter></button-counter>
</div>

prop

Prop 是你可以在组件上注册的一些自定义 属性。当一个值传递给一个 prop 属性的时候,它就变成了那个组件实例的一个 属性

Vue.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
})

<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>

单个根元素

每个组件必须只有一个根元素

v-指令的使用

<div id="blog-posts-events-demo">
  <div :style="{ fontSize: postFontSize + 'em' }">
    <blog-post
      v-for="post in posts"
      v-bind:key="post.id"
      v-bind:post="post"
    ></blog-post>
  </div>
</div>

/data 必须是一个函数
data: function () {
return {
count: 0
}
},
template: ‘You clicked me {{ count }} times.’
})


==组件复用==

```html
<div id="components-demo">
  <button-counter></button-counter>
  <button-counter></button-counter>
  <button-counter></button-counter>
</div>

prop

Prop 是你可以在组件上注册的一些自定义 属性。当一个值传递给一个 prop 属性的时候,它就变成了那个组件实例的一个 属性

Vue.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
})

<blog-post title="My journey with Vue"></blog-post>
<blog-post title="Blogging with Vue"></blog-post>
<blog-post title="Why Vue is so fun"></blog-post>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值