JS-4

ajax

ajax可以让js去读取服务器上面的数据

  • 创建ajax对象
  • 连接到服务器
  • 发送请求(告诉服务器,要哪个文件)
  • 接收返回值

readyState属性:请求状态

  • 0:(未初始化)还没有调用open方法
  • 1:(载入)已调用send()方法,正在发送请求
  • 2:(载入完成)send()方法完成,已收到全部响应内容
  • 3:(解析)正在解析响应内容
  • 4:(完成)响应内容解析完成,可以在客户端调用了

html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="new_ajax.js"></script>
</head>
<script>
  var oBtn = document.getElementById('btn1');

  oBtn.onclick = function(){
    ajax('a.txt', function(str){
      alert(str);
    })
  }
</script>
<body>
<input id="btn1" type="button" value="btn">
</body>
</html>

ajax封装的js

function ajax(url, fnSuccess, fnFaild) {
  // 1. 创建ajax对象
  if (window.XMLHttpRequest) {
    var oAjax = new XMLHttpRequest();
  } else {
    var oAjax = new ActiveXObject('Microsoft.XMLHTTP');
  }
  // 2. 连接到服务器
  // open(方法, 文件名, 异步传输)
  oAjax.open('GET', url, true);
  // 3. 发送请求(告诉服务器,要哪个文件)
  oAjax.send();
  // 4. 接收返回值
  oAjax.onreadystatechange = function () {
    if (oAjax.readyState === 4) { // 读取完成
      if (oAjax.status === 200) { // 成功
        fnSuccess(oAjax.responseText)
      } else {
        if (fnFaild) {
          fnFaild(oAjax.status);
        }
      }
    }
  }
}

JS中:

  • 用没有定义的变量,会报错
  • 用没有定义的属性,undefined

JS面向对象基础

  • 什么是面向对象

    不了解原理的情况下(或者说不清楚内部构造),会使用他的功能。

  • 构造函数:用来构建一个对象👇

<script>
  function createPerson(name, qq) {
    // 原料
    var obj = new Object();

    // 加工
    obj.name = name;
    obj.qq = qq;

    obj.showName = function () {
      alert('我的名字叫:' + this.name);
    }
    obj.showQQ = function () {
      alert('我的QQ:' + this.qq);
    }

    // 出厂
    return obj;
  }

  var obj = createPerson('aaa', '12398700');
  obj.showName();
  obj.showQQ();
</script>
原型:prototype

原型类似于CSS中的行间样式

<script>
  var arr1 = [1, 2, 3, 4];
  var arr2 = [5, 6, 7, 8];
  
  Array.prototype.sum = function () {   // 类似CSS中的class
  // arr1.sum = function(){     // 类似CSS中的行间样式
    var result = 0;
    for (var i = 0; i < this.length; i++) {
      result += this[i];
    }
    return result;
  }

  alert(arr1.sum());
  alert(arr2.sum());
 </script>

构造函数中加属性,原型中加方法

结合后就是下面的这种写法👇

<script>
  function createPerson(name, qq) {
    this.name = name;
    this.qq = qq;
  }

  // 给自己的类添加原型方法
  createPerson.prototype.showName = function () {
    alert('我的名字叫:' + this.name);
  }
  createPerson.prototype.showQQ = function () {
    alert('我的QQ:' + this.qq);
  }

  var obj = new createPerson('aaa', '12398700');
  var obj2 = new createPerson('bbb', '567689798');

  obj.showName();
  obj.showQQ();
  obj2.showName();
  obj2.showQQ();

  alert(obj.showName() === obj2.showName()); // true
</script>

面向对象选项卡demo

一般方法👇

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    #div1 input {
      background: white;
      margin-bottom: 10px;
    }

    #div1 input.active {
      background: wheat;
    }

    #div1 div {
      width: 200px;
      height: 200px;
      background: #ccc;
      display: none;
    }
  </style>
</head>
<script>
  window.onload = function () {
    var oDiv = document.getElementById('div1');
    var aBtn = oDiv.getElementsByTagName('input');
    var aDiv = oDiv.getElementsByTagName('div');

    for (var i = 0; i < aBtn.length; i++) {
      aBtn[i].index = i;
      aBtn[i].onclick = function () {
        for (var j = 0; j < aBtn.length; j++) {
          aBtn[j].className = '';
          aDiv[j].style.display = 'none';
        }
        this.className = 'active';
        aDiv[this.index].style.display = 'block';
      }
    }
  }
</script>

<body>
  <div id="div1">
    <input type="button" value="aaa" class="active">
    <input type="button" value="bbb">
    <input type="button" value="ccc">
    <div style="display: block">cnjasbka</div>
    <div>hfuidb</div>
    <div>buesblcboanl</div>
  </div>
</body>

</html>

把面向过程改写成面向对象的形式,需要:

  • 原则:不能有函数套函数,但可以有全局变量
  • 过程:
    • onload -》 构造函数
    • 全局变量 -》 属性
    • 函数 -》方法
  • 改错
    this/事件/闭包/传参

对象与闭包

  • 通过闭包传递this

面向对象方法改写👇

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    #div1 input {
      background: white;
      margin-bottom: 10px;
    }

    #div1 input.active {
      background: wheat;
    }

    #div1 div {
      width: 200px;
      height: 200px;
      background: #ccc;
      display: none;
    }
  </style>
</head>
<script>
  window.onload = function () {
    new TabSwitch('div1');
  }

  function TabSwitch(id) {
    var _this = this;
    var oDiv = document.getElementById(id);

    this.aBtn = oDiv.getElementsByTagName('input');
    this.aDiv = oDiv.getElementsByTagName('div');

    for (var i = 0; i < this.aBtn.length; i++) {
      this.aBtn[i].index = i;
      this.aBtn[i].onclick = function () {
        _this.fnClick(this);
      }
    }
  }

  TabSwitch.prototype.fnClick = function (oBtn) {
    for (var i = 0; i < this.aBtn.length; i++) {
      this.aBtn[i].className = '';
      this.aDiv[i].style.display = 'none';
    }
    oBtn.className = 'active';
    this.aDiv[oBtn.index].style.display = 'block';
  }
</script>

<body>
  <div id="div1">
    <input type="button" value="aaa" class="active">
    <input type="button" value="bbb">
    <input type="button" value="ccc">
    <div style="display: block">cnjasbka</div>
    <div>hfuidb</div>
    <div>buesblcboanl</div>
  </div>
</body>

</html>

面向对象高级

Json方式的面向对象

不适合多个对象(如果要展示多一个的话就要再var一个json,然后在下面调用。。)

比较适合整个程序中只有一个对象的,比较简单

<script>
  var json = {
    name: 'json',
    qq: '7679606',
    showName: function () {
      alert('我的名字:' + this.name);
    },
    showQQ: function () {
      alert('我的QQ:' + this.qq);
    }
  }

  json.showName();
  json.showQQ();
</script>
继承

继承的是父级的属性和方法

  • call()

关于call继承,先举个例子

  function show(){
    alert(this);
  }
   show();     // [object Window]
   show.call();     // [object Window]
   show.call(12);     // 12

  function show(a, b) {
    alert('this是:' + this + '\na是:' + a + '\nb是' + b);
  }
  show(2, 4); 
  show.call('abc', 3, 6);

<script>
  // 属性的继承
  function A() {
    this.abc = 12;
  }
  A.prototype.show = function () {
    alert(this.abc);
  }

  // B继承A
  function B() {
    // 这里的this 就是 new B() 的意思
    // 通过call来继承父级的属性
    A.call(this);
  }

  //  ——————-———————————————————————————————————————— 


  // 原型的继承
  // B.prototype = A.prototype;   //这样直接将A的prototype赋值给B了之后,如果对B进行操作的话,A也会跟着变化
  for (var i in A.prototype) {
    B.prototype[i] = A.prototype[i];
  }

  B.prototype.fn = function () {
    alert('abc');
  }
  var objB = new B();
  var objA = new A();

  objA.fn();
</script>
拖拽改为面向对象的拖拽demo

原本的

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    #div1 {
      width: 200px;
      height: 200px;
      background: lightcoral;
      position: absolute;
    }
  </style>
</head>
<script>
  window.onload = function () {
    var oDiv = document.getElementById('div1');
    oDiv.onmousedown = function (ev) {
      var oEvent = ev || event;
      var disX = oEvent.clientX - oDiv.offsetLeft;
      var disY = oEvent.clientY - oDiv.offsetTop;

      document.onmousemove = function (ev) {
        var oEvent = ev || event;

        oDiv.style.left = oEvent.clientX - disX + 'px';
        oDiv.style.top = oEvent.clientY - disY + 'px';
      };

      document.onmouseup = function () {
        document.onmousemove = null;
        document.onmouseup = null;
      }
    }
  }
</script>

<body>
  <div id="div1"></div>
</body>

</html>

改写为面向对象

  • 去掉所有的函数嵌套

  • 把公用的东西编程全局变量

  • html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <script src="Drag.js"></script>
  <script src="limitDrag.js"></script>
  <style>
    #div1 {
      width: 200px;
      height: 200px;
      background: lightcoral;
      position: absolute;
    }

    #div2 {
      width: 200px;
      height: 200px;
      background: lightsalmon;
      position: absolute;
    }
  </style>
</head>
<script>
  window.onload = function () {
    new Drag('div1');
    new LimitDrag('div2');
  }
</script>

<body>
  <div id="div1">普通拖拽</div>
  <div id="div2">限制范围拖拽</div>
</body>

</html>
  • Drag.js
function Drag(id) {
  var _this = this;
  this.disX = 0;
  this.disY = 0;

  this.oDiv = document.getElementById(id);
  // this.oDiv.onmousedown = this.fnDown;    // 不能直接将this.fnDown赋值过去,需要在外面套一层
  this.oDiv.onmousedown = function (ev) {
    _this.fnDown(ev);
    return false;
  }
}

Drag.prototype.fnDown = function (ev) {
  var _this = this;
  var oEvent = ev || event;
  this.disX = oEvent.clientX - this.oDiv.offsetLeft;
  this.disY = oEvent.clientY - this.oDiv.offsetTop;

  document.onmousemove = function (ev) {
    _this.fnMove(ev);
  };
  document.onmouseup = function (ev) {
    _this.fnUp(ev);
  };
}

Drag.prototype.fnMove = function (ev) {
  var oEvent = ev || event;

  this.oDiv.style.left = oEvent.clientX - this.disX + 'px';
  this.oDiv.style.top = oEvent.clientY - this.disY + 'px';
};

Drag.prototype.fnUp = function () {
  document.onmousemove = null;
  document.onmouseup = null;
}
  • LimitDrag.js
function LimitDrag(id) {
  Drag.call(this, id); // 继承属性
}

for (var i in Drag.prototype) {
  LimitDrag.prototype[i] = Drag.prototype[i];
}

// 限制拖拽就是在fnMove的时候有不同,所以只需要改写这个方法就行
LimitDrag.prototype.fnMove = function (ev) {
  var oEvent = ev || event;
  var l = oEvent.clientX - this.disX;
  var t = oEvent.clientY - this.disY;

  if (l < 0) {
    l = 0;
  } else if (l > document.documentElement.clientWidth - this.oDiv.offsetWidth) {
    l = document.documentElement.clientWidth - this.oDiv.offsetWidth;
  }

  this.oDiv.style.left = l + 'px';
  this.oDiv.style.top = t + 'px';
};
系统对象

JS 的对象分为三类

  • 本地对象(非静态对象)
    必须得new出来或者实例化出来才可以用。比如:Object,Array,String,Date等
  • 内置对象(静态对象)
    不需要new,不需要实例化,直接就能用的类。比如说 Math (Math.ceil()这种用法)

本地对象和内置对象是JS语言本身所具备的,和他的执行环境无关

  • 宿主对象(由浏览器提供的对象)

    DOM、BOM

BOM

打开、关闭窗口

document.write(‘abc’)
他会先将页面伤的所有内容全部都清空了,然后再将括号里面的内容写进去

<body>
  <!-- <input type="button" value="打开窗口" onclick="window.open('http://www.baidu.com')"> -->
  
  <!-- 注意在FF下,window.close()只能关闭被window.open打开的窗口,而不能关闭原始由用户打开的窗口 -->
  <input type="button" value="关闭窗口" onclick="window.close()">

  <textarea id="txt1" cols="30" rows="10"></textarea>
  <input type="button" value="运行" id="btn1">
</body>

常用属性

  • window.navigator.userAgent
    浏览器类型/操作器类型

  • window.location
    返回当前的网址,也可以赋值

<input type="button" value="aaa" onclick="window.location = 'http://www.baidu.com'">
尺寸及坐标
  • 可视区尺寸

    • document.documentElement.clientWidth;
    • document.documentElement.clientHeight;
  • 滚动距离

    • document.body.scrollTop;
    • document.documentElement.scrollTop;

系统对话框
  • alert(“内容”);没有返回值
  • confirm(“提问的内容”);返回boolean
  • prompt();返回字符串或null
侧边栏广告demo
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
    #div1 {
      width: 100px;
      height: 200px;
      background: lightsalmon;
      position: absolute;
      right: 0;
      bottom: 0;
    }
    body {
      height: 2000px;
    }
  </style>
</head>
<script>
  window.onscroll = window.onresize = function () {
    var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
    var oDiv = document.getElementById('div1');
    oDiv.style.top = document.documentElement.clientHeight - oDiv.offsetHeight + scrollTop + 'px';
  }
</script>
<body>
  <div id="div1"></div>
</body>
</html>

cookie的基础和应用

  • 什么是cookie
    页面用来保存信息的(比如之前输入过邮箱,后来登录的时候那一栏会有之前的邮箱信息。自动登录)

  • cookie的特性

    • 同一个网站(指的是用同一个域名)中所有页面共享一套cookie
    • 数量、大小有限
    • 过期时间
  • JS中使用cookie
    document.cookie()

  • cookie的基本使用

<script>
  var oDate = new Date();
  // oDate.getDate()+80指的是今天开始的8天后的日期
  oDate.setDate(oDate.getDate() + 8);
  alert(oDate.getFullYear() + '-' + (oDate.getMonth() + 1) + '-' + oDate.getDate());

  // cookie 中的 = 是添加的意思,而不是JS中的赋值,所以可以同时添加多个,后面的不会覆盖前面的
  // cookie 如果不指定过期时间的话,到了浏览器关闭时就会被自动清除
  document.cookie = 'name=aaa';
  // expires是内部自带的设置过期时间的属性
  document.cookie = 'password=123456;expires'+= oDate;
  alert(document.cookie);
 </script>

也可以直接在封装一个cookie.js

 <script>
// 封装cookie

  // 设置cookie
  function setCookie(name, value, iDay) {
    var oDate = new Date();
    oDate.setDate(oDate.getDate() + iDay);
    document.cookie = name + '=' + value + ';expires=' + oDate;
  }

  // setCookie('userName', 'doris', 100);
  // setCookie('password', '123456', 100);

  // 获取cookie
  function getCookie(name) {
    var arr = document.cookie.split('; ');
    for (var i = 0; i < arr.length; i++) {
      var arr2 = arr[i].split('=');
      if (arr2[0] === name) {
        return arr2[1];
      }
    }
    return '';
  }

  alert(getCookie('userName'));    // doris


  // 删除cookie
  function removeCookie(name){
    // 这块-1的意思是昨天就已经过期了,浏览器发现后就赶紧删掉了
    setCookie(name, 1, -1);
  }
</script>
cookie登录demo
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style>
  </style>
</head>
<script>
  window.onload = function () {
    var oForm = document.getElementById('form1');
    var oUser = document.getElementsByName('user');

    oForm.onsubmit = function () {
      setCookie('user', oUser.value, 14);
    }

    oUser.value = getCookie('user');
  }

  // 设置cookie
  function setCookie(name, value, iDay) {
    var oDate = new Date();
    oDate.setDate(oDate.getDate() + iDay);
    document.cookie = name + '=' + value + ';expires=' + oDate;
  }

  // 获取cookie
  function getCookie(name) {
    var arr = document.cookie.split('; ');
    for (var i = 0; i < arr.length; i++) {
      var arr2 = arr[i].split('=');
      if (arr2[0] === name) {
        return arr2[1];
      }
    }
    return '';
  }

  // 删除cookie
  function removeCookie(name) {
    // 这块-1的意思是昨天就已经过期了,浏览器发现后就赶紧删掉了
    setCookie(name, 1, -1);
  }
</script>

<body>
  <form action="http://xxx.com.cn" id="form1">
    用户名:<input type="text" name="user"><br>
    密码:<input type="text" name="pass"><br>
    <input type="button" value="登录">
  </form>
</body>

</html>

正则

字符串操作

var str = 'c-njncksn';
// 查询字符。找到返回位置,没找到返回-1
alert(str.search('a'));    // -1

// 字符串截取。2:起点  5:终点  不包括结束为止
alert(str.substring(2, 5));    // jnc
alert(str.substring(2));     // jncksn

// 返回字符串的某一位
alert(str.charAt(3));     // n

// 分割
alert(str.split('-'));    // c,njncksn
找出字符串中所有的数字
<script>
  var str = "jkj 321 jkoj78 -90 njh";

  // 原始写法
  var arr = [];
  var tmp = '';
  for (var i = 0; i < str.length; i++) {
    if (str[i].charAt(i) >= 0 && str.charAt(i) <= 9) {
      tmp += str.charAt(i);
    } else {
      if (tmp) {
        arr.push(tmp);
        tmp = '';
      }
    }
  }
  if (tmp) {
    arr.push(tmp);
    tmp = '';
  }
  alert(arr);     // 321,78,90

  // 正则写法
  alert(str.match(/\d+/g));     // 321,78,90
</script>
RegExp对象
  • JS风格 new RegExp(‘a’, ‘i’);
  • perl风格 /a/i;
i(ignore)就是忽略大小写
\d 在正则中就是数字的意思
g(global)全局匹配的意思
+ 是量词(个数),代表若干个
str.search(re) 找出位置
str.match(re) 把所有匹配的东西全部都提取出来
replace() 替换所有匹配,返回替换后的字符串
  // 这块的这个i(ignore)就是忽略大小写的意思
  var re = new RegExp('a', 'i');
  var str = 'xiani';
  alert(str.search(re)); // 2

  var re = /a/i;
  var str = 'xiAni';
  alert(str.search(re)); // 2


  var str = "ncaj k180njkc nasj12"
  var re = /\d/; // 匹配数字
  alert(str.search(re)); // 6   找出的位置


  // match  把所有匹配的东西全部都提取出来
  var re = /\d/; // 匹配数字
  alert(str.match(re)); // 这个时候只能找出str中的第一个数字


  var re = /\d/g; // 全局匹配数字
  alert(str.match(re)); // 1,8,0,1,2    这块所有的数字都是分开的


  var re = /\d\d/g; // 全局匹配 两位数字
  alert(str.match(re)); // 18,12


  var re = /\d\d\d/g; // 全局匹配 三位数字
  alert(str.match(re)); // 180


  // 这块的这个 + 是量词(个数),代表若干个
  var re = /\d+/g; // 全局匹配数字
  alert(str.match(re)); // 180,12



  var str = 'nca 1cnaaa';
  var re = /a/g;
  alert(str.replace(re, 0));     // nc0 1cn000

  var str = 'jdbbjdiojasaajiosejaacc'
  var re = /aa|bb|cc/g;
  alert(str.replace(re, '**'));     // jd**jdiojas**jiosej****
[] - 元字符
^ 排除
  var str = 'apc bpc cpc dpc dpv apr';
  var re = /[abc]pc/g;
  alert(str.match(re)); // apc,bpc,cpc

  var str = 'djs890n-cjakn321-';
  //  下面这种写法和  /\d+/g 是一样的
  var re = /[0-9]+/g;
  alert(str.match(re)); // 890,321
  var re1 = /[a-z]+/g;
  alert(str.match(re1)); // djs,ncjakn

  // 下面的意思是除了英文字母之外的
  var re2 = /[^a-z]+/g;
  alert(str.match(re2)); // 890,-,321-
  var re3 = /[^a-z0-9]+/g;
  alert(str.match(re3)); // -,-
过滤html标签
var str = '<html>cnisnckan<p>bcjdsbacn<span>///</span>vdsa<p>cwea</html>'
var re = /<[^<>]+>/g;
alert(str.replace(re, ''));     // cnisnckanbcjdsbacn///vdsacwea
转义字符
  • \d 数字 [0-9]
  • \w 英文、数字、下划线 [a-z0-9]
  • \s 空白字符
  • \D 除了 数字 [ ^0-9]
  • \W 除了 英文、数字、下划线 [ ^a-z0-9]
  • \S 非空白字符
量词:个数
  • {n} 正好出现n次

  • {n,m} 最少n次,最多m次

  • {n,} 最少n次,最多不限

    • 相当于{1,} ,就是最少1次,最多不限
      
  • ? {0, 1}, 最少0次,最多1次

    • {0,} 可以没有,也可以有,并且有多少位都行 尽量不要用
  • 校验座机号码
    \d{8} 8位数字 但是这样写的话也不可以,因为这样的话第一位可以是0 所以正常应该这么写:[0-9]\d{7}

  • 校验QQ 5-11位
    [1-9]\d[4,10]

  • 固定电话的校验
    比如说下面的这两种电话,加不加区号都可以拨打:010-11223344 或者 11223344
    (0\d[2,3]-)?[1-9]\d{7}
    也可以在后面加个分机号 (-\d{1,5})?
    (0\d[2,3]-)?[1-9]\d{7}(-\d{1,5})?

^ 行首
$ 行尾
邮箱校验
<script>
  window.onload = function () {
    var oTxt = document.getElementById('txt1');
    var oBtn = document.getElementById('btn1');

    oBtn.onclick = function () {
      // cjakbc@ncjans.askn  
      // 邮箱规则:一串英文/数字/下划线 @ 一串英文/数字 . 一串英文
      // \w+ @ [a-z0-9]+ \. [a-z]+

      // var re = /\w+@[a-z0-9]+\.[a-z]+/i;
      // 加了 ^ $ 的意思就是从这个字符串的开始到结尾
      // 中间只能出现我们写的校验规则符合的内容
      // var re = /^\w+@[a-z0-9]+\.[a-z]+$/i;
      var re = /^\w+@[a-z0-9]+\.[a-z]{2,4}$/;

      if (re.test(oTxt.value)) {
        alert('合法的邮箱');
      } else {
        alert('邮箱不正确');
      }
    }
  }
</script>
<body>
  <input type="text" id="txt1">
  <input type="button" value="校验" id="btn1">
</body>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值