百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

web前端入门JavaScript笔记三 JS 对象

lipiwang 2024-11-04 14:36 13 浏览 0 评论

学习大纲

一、事件对象【★】

1、概述

用于存储事件的信息

? 说明

? 事件对象是由用户产生的(鼠标单击或者按一下键盘)

? 事件对象存储 对应 事件信息

? 事件对象存储信息有:

事件的类别,如:click,keydown等等

点击事件的位置

点击的哪一个键

等等

? 用于阻止事件流,用于阻止浏览器默认动作;

2、获取事件对象

? ie6、7、8

通过关键词event获取

nodeObj.onclick = function() {
window.event
}

? 主流浏览器

通过方法第一个参数获取

nodeObj.onclick = function(evt) {
evt
}

思考:形参为什么不写event系统关键词不要用,一般用evt

? 兼容

nodeObj.onclick = function(evt) {
var evt = window.event ? window.event : evt;
}

3、事件对象的作用

1)判断是否回车表单提交


<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
 <style type="text/css">
 #div1 {width: 800px; height: 800px; background: red; }
   #div2 {width: 400px; height: 400px; background: blue;}
     #div3 {width: 200px; height: 200px; background: green; }
 </style>
</head>
<body>
 <form action="提交给老范.html" id="form1">
   <input type="text" name="">
   <input type="submit" value="提交">
 </form>
<script>
window.onkeydown = function(evt) {
 var evt = window.event ? window.event : evt;
 // console.log(evt);
 // 当表单按下回车键则提交
 if (evt.keyCode == 13) {
   var form1Obj = document.getElementById('form1');
   form1Obj.submit();
 }
}
</script>
</body>
</html>

说明:完善表单提交瑕疵,当获取焦点的时候可以按回车键直接提交,但是没有获取焦点就通过js触发提交(but 必须判断只能是回车键才可以提交)

2)阻止浏览器默认动作

? 说明

DOM1级事件 return false;

DOM1级事件或者DOM2级事件 evt.preventDefault();

? 案例

阻止用户提交表单

3)事件对象中记录的鼠标位置

? 说明

evt.screenX 相对于屏幕的左上角为原点

evt.screenY

evt.clientX 相对于浏览器的客户端左上角为原点(不计算滚动条位置)

evt.clientY

evt.pageX 相对于浏览器的客户端左上角为原点(计算滚动条的位置)

evt.pageY

evt.offsetX 以自己的左上角为原点

evt.offsetY

? 图解

? 案例

点击增加水果

<script>
document.body.style.backgroundImage="url('ft/bj.jpg')";
   document.body.style.backgroundSize='1366px 768px';
   document.onclick=function(evt){
        imgobg = document.createElement('img');
       i = parseInt(10*Math.random());
       imgobg.setAttribute('src','ft/sg/'+i+'.png');
       imgobg.style.width="100px";
       //随机显示位置
       imgobg.style.position = 'absolute';
       imgobg.style.top = evt.clientY + 'px';
       imgobg.style.left = evt.clientX + 'px';
       document.body.appendChild(imgobg);
   }
   </script>

4)阻止事件流

? 说明:

? ie6、7、8:event.cancelBubble=true;

? 主流浏览器:evt.stopPropagation();

面向对象OOP

一、概念

在面向对象编程中,类(class)是对象(object)的模板,定义一组对象公有的属性和方法(类是抽象的,对象具体的)

? 在PHP中,可以通过实例化一个类来获取对象

? 而在JavaScript中没有“类”,但是可以用过另一种方法定义自定义“类”,然后创建

对象,也可以直接创建对象(对象可以有默认成员,也可以后期动态添加成员)

总结:在js里可以通过多种方式创建对象

二、JavaScript中“类”的种类

1、系统类

1)Array类

var arr = new Array();

var arr2 = new Array();

属性

对象.length 获取数组的长度

方法

对象.pop() 弹出数组的最后一个元素,并返回弹出的值

对象.push(n); 给数组添加一个元素,并返回新数组的长度

等等

2)Date类

3)Math类

4)String类

2、自定义类 (构造函数)

1)概念

? 明确:类(class)是对象(object)的模板,然后“对象”根据这个模板生成。

? 说明1:JS语言中使用构造函数(constructor)作为对象的模板。所谓构造函数,

就是提供一个生成对象的模板,并描述对象的基本结构的函数。

? 说明2:一个构造函数,可以生成多个对象,每个对象都有相同的结构。

2)定义构造函数

fucntion 函数名() {

}

经验总结:构造函数一般情况下函数名首字母大写

︴思考: 思考如果通过构造函数创建对象

通过new关键词+函数名()即可创建对象

三、通过构造函数创建对象

1、 通过构造函数创建对象

? 代码

说明:函数名不区分大小写,但是强烈推荐大写

︴思考: 构造函数和普通函数有什么区别?

答:没有区别,如果直接调用则是普通函数,如果是new+函数名()则构造函数,用于创建对象

脚下留心:不要声明构造函数,当普通函数使用(所以为了明确后期构造函数就使用new实例化,普通函数就直接调用则通过函数名首字母来区分是构造函数还是普通函数)

︴练习: 描述一个人的信息

? 提出问题

如何将php面向对象代码(code)转换为 js面向对象代码(code)

? 分析步骤

? 定义Person构造函数

? 丰富Person构造函数成员(属性和方法)

? 创建对象

? 解决问题

<script>
   //定义构造函数
   function Preson(){
   
       //使用this定义名称属性
       this.name='郭美美';
       //使用this定义年龄属性
       this.age = 28;
       console.log(type);
       
   }
   //2.创建对象
   peObj = new Preson();
 
   console.log(peObj);
   
</script>

︴思考:如果给构造函数传递参数

答:仿普通方法传参


︴思考: js中this含义,如何使用?

1)BOM中,代表window对象

证明


2)在事件中,代表元素/节点对象

证明.

3)在函数/方法里边 代表调用该函数/方法的当前对象

证明.

4)在面向对象封装概念中【★】

? 通过this来声明类的公有属性

? 通过var来声明类的私有属性

证明.



四、构造函数成员管理

1、成员属性

var 变量名 = 值; //添加私有成员

this.变量名 = 值; //添加公有成员

2、成员方法

var 方法名 = function() {} //添加私有方法成员

this.方法名 = function() {} //添加公有方法成员

︴练习

定义人构造函数,设置姓名属性和eat方法 并 创建对象输出和调用


︴思考: 如果是上述代码是name是私有属性,外面如何输出

答:明确,外面不能直接输出

解决:通过内部方法调用私有属性


︴思考: 如果给对象添加属性和方法?是否会影响构造函数?

答:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
</head>
<body>
<script type="text/javascript">
//定义人构造函数,设置姓名属性和eat方法 并 创建对象输出和调用
function Person() {
 //定义姓名属性
 this.name = '张三';
 this.getName = function() {
   console.log(name);
 }
 //定义eat方法
 this.eat = function() {
   alert('吃饭日语');
 }
}
//创建对象
var obj = new Person();
console.log(obj);
//输出obj对象里的name属性
console.log(obj.name); //张三
//修改obj的name属性
obj.name = '赵四';
console.log(obj.name);
//创建对象2
var obj1 = new Person();
console.log(obj1.name);
</script>
</body>
</html>

︴练习1:删除对象属性

语法:delete 对象.属性


︴练习2:遍历对象成员

1)语法

for (变量名 in 对象) {


}

脚下留心:变量名指的是对象的键

2)使用




五、 获取构造器(constructor)

1、说明:

通过指定构造函数创建对象,那么我们称该对象的 构造函数名称 为构造器

function Fn() {}

var obj = new Fn(); obj对象构造器是:fn

function Fun2() {}

var obj = new Fun2(); obj对象构造器是:Fun2

2、语法

获取对象构造器:对象.constructor

返回对象的类型:typeof 变量名 或者 typeof(变量名)

判断对象是否是指定构造函数的实例:对象 instanceof 构造器

3、练习


︴JS高级1判断是否是数组


■知识点综合练习

? 题1

下述代码唯一的区别就是首字母大小写,没有其他区别;都是构造函数 (对的)

? 题2


function Animal(){
 this.weight = 120;
 this.eat = function(){
   alert('动物想吃饭');
 }
}
var obj = new Animal();
var obj2 = obj;
console.log(obj.weight);     //120
console.log(obj2.weight);    //120
obj.weight = 88;
console.log(obj.weight);    //88
console.log(obj2.weight);   //88

? 题3

function Animal(){
 this.weight = 120;
 this.eat = function(){
   alert('动物想吃饭');
 }
}
var obj = new Animal();
delete obj.weight;
console.log(obj.weight);//undefined

六、对象在内存中的分配

1、说明

栈:基本类数据和符合类型的变量名称

堆:符合类型数据

代码区:函数

静态成员区:静态成员

2、案例1

<script type="text/javascript">
function Animal(){
this.weight = 120;
this.eat = function(){
 alert('动物想吃饭');
}
}
var dog1=new Animal();
var dog2=new Animal();
</script>

图解如下:


3、案例扩展1

function Animal(){
 this.weight = 120;
 this.eat = function(){
   alert('动物想吃饭');
 }
}
var obj = new Animal();
var obj2 = obj;
复合类型都是引用传值(前提将a对象赋给b对象)

图解如下:


七、JSON对象【★★】

1、什么是json对象

json是一种轻量级的数据交换格式,json数据也可以称之为json对象,因为它的数据以“键值对”形式组合成一个对象;

2、json对象的定义

1)语法

语法:var obj = {属性名:值, 属性名N:值}

? 通过“{}”创建对象

? 属性名可以加引号,也可以不加引号

? 属性值根据类型判断是否加引号

? 对象的成员由:属性名和值组成,多个成员之间用“,”逗号隔开(注:属性名和值

之间用冒号“:”隔开)

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
</head>
<body>
 
<script type="text/javascript">
//语法:var obj = {属性名:值, 属性名:值}
//练习1:创建空对象
var obj = {};
console.log(obj);
//练习2:给对象添加name成员
var obj = {"name": '张三'}
console.log(obj);
</script>
</body>
</html>

2)练习:如何使用json表示1个人的信息:姓名,性别,年龄

var obj = {name:"战三", sex: "公", age: 18}




3)练习:如何使用json表示N个人的信息

通过数组存放,数组的每个元素是一个json对象

var arr = [

{name:"战三", sex: "公", age: 18},

{name:"战三", sex: "公", age: 18},

{name:"战三", sex: "公", age: 18},

{name:"战三", sex: "公", age: 18}

];

3、json对象成员的使用,添加方法

4、php中的json操作

1)说明

在实际工作,php经常会将从数据库中获取的数据转化为JSON格式,然后交给js处理

2)语法

json_encode(关联数组) 将数组转化为json格式数据

json_decode(json数据,[true | false])参数二可选参数:false-转化为对象,true-转化为数组

<?php
//连接数据库获取数据,一般存到数组
$arr = array(
 array('id' => 1, 'name' => 1, 'age' => 1),
 array('id' => 1, 'name' => 1, 'age' => 1),
 array('id' => 1, 'name' => 1, 'age' => 1),
 array('id' => 1, 'name' => 1, 'age' => 1),
 array('id' => 1, 'name' => 1, 'age' => 1)
);
//将数据转化为json格式
$jsonData = json_encode($arr);
var_dump($jsonData);
//将json数据转化为数组或者对象,默认是对象
$lastData = json_decode($jsonData);
var_dump($lastData);
$lastData = json_decode($jsonData, true);
var_dump($lastData);
?>
<ul>
 <li>1111</li>
</ul>
<script type="text/javascript">
// var arr = [{"id":1,"name":1,"age":1},{"id":1,"name":1,"age":1},{"id":1,"name":1,"age":1},{"id":1,"name":1,"age":1},{"id":1,"name":1,"age":1}]
// console.log(arr);
</script>

脚下留心:将数据转化为json数据参数必须是关联数组

6、练习


<?php
//连接数据库获取数据,一般存到数组
$arr = array(
 array('id' => 1, 'name' => '张安', 'age' => 1),
 array('id' => 1, 'name' => '大是大非', 'age' => 1),
 array('id' => 1, 'name' => 1, 'age' => 1),
 array('id' => 1, 'name' => 1, 'age' => 1),
 array('id' => 1, 'name' => 1, 'age' => 1)
);
$jsonData = json_encode($arr);
//var_dump($jsonData); [{"id":1,"name":1,"age":1},{"id":1,"name":1,"age":1},{"id":1,"name":1,"age":1},{"id":1,"name":1,"age":1},{"id":1,"name":1,"age":1}]   输出字符串,但是在js中就是数组和对象
?>
<ul></ul>
<script type="text/javascript">
//1.将php中的数据赋给js变量
var jsonData = <?php echo $jsonData; ?>;
//2.创建html变量用于存放数据
var html = '';
//3.循环拼接数据
for (var i = 0; i < jsonData.length; i++) {
 //3.1 获取单个对象
 var tmpObj = jsonData[i];
 html += '<li>ID:'+tmpObj.id+',名称:'+tmpObj.name+',年龄:'+tmpObj.age+'</li>'
}
//4.获取ul节点对象
var ulObj = document.getElementsByTagName('ul')[0];
//4.1將内容放到ul标签中
ulObj.innerHTML = html;
// var arr = [{"id":1,"name":1,"age":1},{"id":1,"name":1,"age":1},{"id":1,"name":1,"age":1},{"id":1,"name":1,"age":1},{"id":1,"name":1,"age":1}]
// console.log(arr);
</script>

7、思考题

大家想一想:使用json对象和使用构造器获得的对象分别适应于怎样的应用场景?

八、函数的各种执行方式

1、说明

函数

直接函数名加小括号

通过new关键词加构造函数名

通过对象点方法名调用

通过call方法和apply方法调用:这两个方法作用一样,区别在于传参格式不一样(作用:用于指定对象调用函数)

? 说明

默认调用函数是通过window对象

2、语法

函数.call(对象, 参数1,参数2,参数3,参数4)

函数.apply(对象, array(参数1,参数2,参数3))

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
</head>
<body>
 
<script type="text/javascript">
//1.定义普通函数fn1
function fn1(param1, param2) {
 //调用该函数的当前对象
 console.log(this);
 console.log('用户名:'+this.name+',年龄:'+this.age);
 console.log('参数1:'+param1+',参数2:'+param2);
}
//2.定义jsonObj对象
var jsonObj = {name: '赵四', age: 18};
//3.语法:  函数.call(对象)   函数.apply(对象)
fn1.call(jsonObj, 1, 2);
fn1.apply(jsonObj, [1, 2]);
// 上午练习code
// function fn() {
//  alert(1);
//  console.log(this);
// }
// console.log(fn);
// console.log(window.fn);
// fn();
// window.fn();
</script>
</body>
</html>

? 说明

? call和apply都是用户指定对象调用函数(注:默认是window对象)

? call和apply的区别 对象后面的实参格式不一样: call方法传递多个参数,多个参

数之间用逗号隔开;apply用数组传递

? call和apply第一个参数后面的实参都是 可选参数

九、面向对象

︴说明

面向对象的三大特效:封装,继承,多态

1、封装

? 在js中只有私有成员和公有成员,但是不能使用php中的public和private修饰符来修饰。

? 在js中通过,this来声明公有成员

? 在js中通过,var来声明私有成员

脚下留心:私有属性不可以在构造函数外面使用,可以在内部声明函数调用内部私有属性

2、继承(★)

1)原型继承prototype介绍

? 在PHP中,一个类可以继承另一个类,子类可以使用父类的属性和方法

? 在js中,一个构造函数可以继承一个对象,继承后构造函数拥有该对象的成员

继承关键字:prototype

2)原型继承prototype定义

? 继承可以继承一个成员,也可以继承多个成员

? 继承单个成员:构造函数.prototype.成员名称 = 值;

? 继承多个成员:构造函数.prototype = 对象;

︴继承单一成员练习

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
</head>
<body>
 
<script type="text/javascript">
//定义人的构造函数
function Person(name,age) {
 //定义公有属性name
 this.name = name;
 this.age = age;
}
//通过原型继承给 构造函数添加 sex 成员, 语法:函数.prototype.成员属性 = 值
Person.prototype.sex = '男';
//创建对象
var obj = new Person('PHP9', 18);
console.log(obj);
console.log(obj.sex);
</script>
</body>
</html>

︴继承多个成员练习

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
</head>
<body>
 
<script type="text/javascript">
//定义人的构造函数
function Person(name,age) {
 //定义公有属性name
 this.name = name;
 this.age = age;
}
//声明对象
var jsonObj = {sex: '男', a: 123, b: 456}
//通过原型继承给 构造函数添加 多个成员, 语法:函数.prototype = 对象
Person.prototype = jsonObj;
//创建对象
var obj = new Person('PHP9', 18);
console.log(obj);
console.log(obj.name);
console.log(obj.sex);
console.log(obj.a);
console.log(obj.b);
</script>
</body>
</html>

3)原型继承的注意事项

? 继承对象的成员 与 本身成员名称一致,体现本身成员结果

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
</head>
<body>
 
<script type="text/javascript">
//定义人的构造函数
function Person(name,age) {
 //定义公有属性name
 this.name = name;
 this.age = age;
 this.sex = '女';
}
//声明对象
var jsonObj = {sex: '男', a: 123, b: 456}
//通过原型继承给 构造函数添加 多个成员, 语法:函数.prototype = 对象
Person.prototype = jsonObj;
//创建对象
var obj = new Person('PHP9', 18);
console.log(obj);
console.log(obj.name);
console.log(obj.sex);
</script>
</body>
</html>

? 对象和单一成员同时继承,需要先继承对象、再继承单一成员

? 多个对象 同时继承,最后对象起作用

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
</head>
<body>
 
<script type="text/javascript">
//定义人的构造函数
function Person(name,age) {
 //定义公有属性name
 this.name = name;
 this.age = age;
}
//声明对象
var jsonObj = {sex: '男', a: 123, b: 456}
//通过原型继承给 构造函数添加 多个成员, 语法:函数.prototype = 对象
Person.prototype = jsonObj;
var jsonObj1 = {sex1: '男', a1: 123, b1: 456}
Person.prototype = jsonObj1;
var jsonObj2 = {sex2: '男', a2: 123, b2: 456}
Person.prototype = jsonObj2;
//创建对象
var obj = new Person('PHP9', 18);
console.log(obj);
</script>
</body>
</html>

3、多态

多态顾名思义多种形态,在js中没有固定的多态的执行语句,但是可以通过另一种方式显示

? 通过函数体内的arguments对象来实现

? 通过函数执行的call和apply函数来实现

4、静态成员

1)概念

当一个构造函数实例化出多个对象,多个对象调用一个固定不变的成员时,这时候该变量声明静态成员。

2)静态变量的好处

? 静态成员属于构造函数,可以更快使用

? 减少内存占用

3)语法

构造函数.静态成员名称 = 值;

4)使用


<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
</head>
<body>
 
<script type="text/javascript">
//定义人的构造函数
function Person(name,age) {
 //定义公有属性name
 this.name = name;
 this.age = age;
}
//添加静态成员 version  
Person.version = '1.0';
//使用静态成员
console.log(Person.version);
</script>
</body>
</html>

十、异常(Exception)

1、概念

代码一旦出错,后面的代码就终止执行,这样用户体验不好。我们希望一旦有错误就抛出异常,异常处理完毕后继续执行。

2、语法

try {


}catch(ex) {


}

try 检查代码

catch 捕捉异常

finally 不过是否存在异常,都会走该代码段

ex 存放错误信息

脚下留心:抛出异常只针对执行错误

3、练习


<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
</head>
<body>
 
<script type="text/javascript">
try {
 function F1() {
 }
 var obj = new F12();
} catch(ex) {
 console.log(ex);
} finally {
 console.log('不管是否有错误,都执行一次');
}
</script>
</body>
</html>

相关推荐

前端入门——css 网格轨道详细介绍

上篇前端入门——cssGrid网格基础知识整体大概介绍了cssgrid的基本概念及使用方法,本文将介绍创建网格容器时会发生什么?以及在网格容器上使用行、列属性如何定位元素。在本文中,将介绍:...

Islands Architecture(孤岛架构)在携程新版首页的实践

一、项目背景2022,携程PC版首页终于迎来了首次改版,完成了用户体验与技术栈的全面升级。作为与用户连接的重要入口,旧版PC首页已经陪伴携程走过了22年,承担着重要使命的同时,也遇到了很多问题:维护/...

HTML中script标签中的那些属性

HTML中的<script>标签详解在HTML中,<script>标签用于包含或引用JavaScript代码,是前端开发中不可或缺的一部分。通过合理使用<scrip...

CSS 中各种居中你真的玩明白了么

页面布局中最常见的需求就是元素或者文字居中了,但是根据场景的不同,居中也有简单到复杂各种不同的实现方式,本篇就带大家一起了解下,各种场景下,该如何使用CSS实现居中前言页面布局中最常见的需求就是元...

CSS样式更改——列表、表格和轮廓

上篇文章主要介绍了CSS样式更改篇中的字体设置Font&边框Border设置,这篇文章分享列表、表格和轮廓,一起来看看吧。1.列表List1).列表的类型<ulstyle='list-...

一文吃透 CSS Flex 布局

原文链接:一文吃透CSSFlex布局教学游戏这里有两个小游戏,可用来练习flex布局。塔防游戏送小青蛙回家Flexbox概述Flexbox布局也叫Flex布局,弹性盒子布局。它决定了...

css实现多行文本的展开收起

背景在我们写需求时可能会遇到类似于这样的多行文本展开与收起的场景:那么,如何通过纯css实现这样的效果呢?实现的难点(1)位于多行文本右下角的展开收起按钮。(2)展开和收起两种状态的切换。(3)文本...

css 垂直居中的几种实现方式

前言设计是带有主观色彩的,同样网页设计中的css一样让人摸不头脑。网上列举的实现方式一大把,或许在这里你都看到过,但既然来到这里我希望这篇能让你看有所收获,毕竟这也是前端面试的基础。实现方式备注:...

WordPress固定链接设置

WordPress设置里的最后一项就是固定链接设置,固定链接设置是决定WordPress文章及静态页面URL的重要步骤,从站点的SEO角度来讲也是。固定链接设置决定网站URL,当页面数少的时候,可以一...

面试发愁!吃透 20 道 CSS 核心题,大厂 Offer 轻松拿

前端小伙伴们,是不是一想到面试里的CSS布局题就发愁?写代码时布局总是对不齐,面试官追问兼容性就卡壳,想跳槽却总被“多列等高”“响应式布局”这些问题难住——别担心!从今天起,咱们每天拆解一...

3种CSS清除浮动的方法

今天这篇文章给大家介绍3种CSS清除浮动的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。首先,这里就不讲为什么我们要清楚浮动,反正不清除浮动事多多。下面我就讲3种常用清除浮动的...

2025 年 CSS 终于要支持强大的自定义函数了?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!1.什么是CSS自定义属性CSS自...

css3属性(transform)的一个css3动画小应用

闲言碎语不多讲,咱们说说css3的transform属性:先上效果:效果说明:当鼠标移到a标签的时候,从右上角滑出二维码。实现方法:HTML代码如下:需要说明的一点是,a链接的跳转需要用javasc...

CSS基础知识(七)CSS背景

一、CSS背景属性1.背景颜色(background-color)属性值:transparent(透明的)或color(颜色)2.背景图片(background-image)属性值:none(没有)...

CSS 水平居中方式二

<divid="parent"><!--定义子级元素--><divid="child">居中布局</div>...

取消回复欢迎 发表评论: