(根据居然老师直播课内容整理)

一、页面功能简介

  • 在“用户中心”的任一界面,点击左边“收货地址”后,显示下面界面
  • 此界面包括以下4个功能:
    • 新增收货地址
    • 删除当前收货地址
    • 编辑(当前记录收货地址)
    • 设为默认
  • 以4个功能中,“新增收货地址”和“编辑” 需要弹出表单,进行编辑

二、显示收货地址信息页面

1、实现分析

  • 在“用户中心”的任一界面,点击左边“收货地址”
  • 前端向后端发起 user/addresses路由发起 get请求
  • 后端接收请求,判断用户是否登录
  • 如果已登录,返回页面
  • 如果未登录,跳转到登录页面

2、后端veiw实现

  • 用户登录后才能使用此功能
#  /apps/users/views.py class AddressView(LoginRequiredMixin, View):"""用户收货地址"""def get(self, request):"""提供收货地址界面"""return render(request, 'user_center_site.html')

3、路由注册

    #  /apps/users/urls.py # 展示用户地址path('addresses/', views.AddressView.as_view(),name="addresses"),

三、收货地址数据模型

  • 用户地址模型类定在users应用的models.py中

1、收货地址模型类

class Address(BaseModel):"""用户地址"""user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='addresses', verbose_name='用户')title = models.CharField(max_length=20, verbose_name='地址名称')receiver = models.CharField(max_length=20, verbose_name='收货人')province = models.ForeignKey('areas.Area', on_delete=models.PROTECT, related_name='province_addresses', verbose_name='省')city = models.ForeignKey('areas.Area', on_delete=models.PROTECT, related_name='city_addresses', verbose_name='市')district = models.ForeignKey('areas.Area', on_delete=models.PROTECT, related_name='district_addresses', verbose_name='区')place = models.CharField(max_length=50, verbose_name='地址')mobile = models.CharField(max_length=11, verbose_name='手机')tel = models.CharField(max_length=20, null=True, blank=True, default='', verbose_name='固定电话')email = models.CharField(max_length=30, null=True, blank=True, default='', verbose_name='电子邮箱')is_deleted = models.BooleanField(default=False, verbose_name='逻辑删除')class Meta:db_table = 'tb_address'verbose_name = '用户地址'verbose_name_plural = verbose_nameordering = ['-update_time']  # 按 update_time倒序  排序

2、收货地址模型类说明

  • 收货地址模型类中省、市、县的外键指向areas/models里面的Area。

    • 指明外键时,可以使用应用名.模型类名来定义,也可以使用模型类
  • ordering表示在进行收货地址模型查询时,默认使用的排序方式。
    • ordering = [’-update_time’] : 根据更新的时间倒叙。

3、补充用户模型默认地址字段

  • 默认地址字段应保存到user表中,与用户绑定,需要修改User模型

4、数据库迁移

python manage.py makemigrations
python manage.py migrate

四、新增用户收货地址

1、接口设计和定义

1.1 请求方式:

选项 方案
请求方法 POST
请求地址 /users/addresses/create/

1.2 请求参数 :

参数名 类型 是否必传 说明
eceiver string 收货人
province_id string 省份ID
city_id string 城市ID
district_id string 区县ID
place string 收货地址
mobile string 手机号
tel string 固定电话
email string 邮箱

1.3 响应结果 : json

响应结果 响应内容
code 状态码
errmsg 错误信息
id 地址ID
receiver 收货人
province 省份名称
city 城市名称
district 区县名称
place 收货地址
mobile 手机号
tel 固定电话
email 邮箱

2、后端view实现

  • 判断用户是否登录
  • 接收参数
    • post参数存放在request.body中
  • 校验参数
    • 必传参数量否传递
    • 手机号校验
    • 如果填有固定电话,固定电话需要校验
    • 如果填了邮箱,邮箱需校验
  • 保存到数据库
  • 根据前端需要,返回详细数据
class AddressCreateView(LoginRequiredJSONMixin, View):"""新增地址"""def post(self,request):# 接收参数json_dict=json.loads(request.body.decode())receiver = json_dict.get('receiver')province_id = json_dict.get('province_id')city_id = json_dict.get('city_id')district_id = json_dict.get('district_id')place = json_dict.get('place')mobile = json_dict.get('mobile')tel = json_dict.get('tel')email = json_dict.get('email')# 验证if not all([receiver,province_id,city_id,district_id,place,mobile]):return http.HttpResponseForbidden('缺少必传参数')if not re.match(r"^1[3-9]\d{9}$", mobile):return http.HttpResponseForbidden('参数mobile有误')if tel and not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):return http.HttpResponseForbidden('参数固定电话有误')if not email and not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):return http.HttpResponseForbidden('参数email有误')# 保存try:address = Address.objects.create(user=request.user,title=receiver,receiver=receiver,province_id=province_id,city_id=city_id,district_id=district_id,place=place,mobile=mobile,tel=tel,email=email,)except Exception as e:logging.error(e)return http.HttpResponseServerError({"code": RETCODE.DBERR, "errmsg": "新增收获地址失败"})# 响应address_dict = {"id": address.id,"receiver": address.receiver,"province": address.province.name,"city": address.city.name,"district": address.district.name,"place": address.place,"mobile": address.mobile,"tel": address.tel,"email": address.email}return http.JsonResponse({"code": RETCODE.OK, "errmsg": "新增收货地址成功", "address": address_dict})

3、定义路由

4、前端实现

4.1 新增地址JS

        // 新增地址save_address(){if (this.error_receiver || this.error_place || this.error_mobile || this.error_email || !this.form_address.province_id || !this.form_address.city_id || !this.form_address.district_id ) {alert('信息填写有误!');} else {// 新增地址let url = '/users/addresses/create/';axios.post(url, this.form_address, {headers: {'X-CSRFToken':getCookie('csrftoken')},responseType: 'json'}).then(response => {if (response.data.code == '0') {// 局部刷新界面:展示所有地址信息,将新的地址添加到头部this.addresses.splice(0, 0, response.data.address);this.is_show_edit = false;} else if (response.data.code == '4101') {location.href = '/login/?next=/users/addresses/';} else {alert(response.data.errmsg);}}).catch(error => {console.log(error.response);})}},

4.2 新增地址html

<form><div class="form_group"><label>*收货人:</label><input v-model="form_address.receiver" @blur="check_receiver" type="text" class="receiver"><span v-show="error_receiver" class="receiver_error">请填写收件人</span></div><div class="form_group"><label>*所在地区:</label><select v-model="form_address.province_id"><option v-for="province in provinces" :value="province.id">[[ province.name ]]</option></select><select v-model="form_address.city_id"><option v-for="city in cities" :value="city.id">[[ city.name ]]</option></select><select v-model="form_address.district_id"><option v-for="district in districts" :value="district.id">[[ district.name ]]</option></select></div><div class="form_group"><label>*详细地址:</label><input v-model="form_address.place" @blur="check_place" type="text" class="place"><span v-show="error_place" class="place_error">请填写地址信息</span></div><div class="form_group"><label>*手机:</label><input v-model="form_address.mobile" @blur="check_mobile" type="text" class="mobile"><span v-show="error_mobile" class="mobile_error">手机信息有误</span></div><div class="form_group"><label>固定电话:</label><input v-model="form_address.tel" @blur="check_tel" type="text" class="tel"><span v-show="error_tel" class="tel_error">固定电话有误</span></div><div class="form_group"><label>邮箱:</label><input v-model="form_address.email" @blur="check_email" type="text" class="email"><span v-show="error_email" class="email_error">邮箱信息有误</span></div><input @click="save_address" type="button" name="" value="新 增" class="info_submit"><input @click="is_show_edit=false" type="reset" name="" value="取 消" class="info_submit info_reset">
</form>

5、后端优化

5.1 用户地址不能超过限制,提交后端后就需要判断

  • 前端提交后,应首先判断用户收货地址数据量是否超过上限,
  • 用户信息可以通过request.user得到

5.2 设置默认收货地址

  • 新增第一个地址时,应该添加为默认收货地址
  • 或者新增时,判断一下用户默认地址是否为空,如果为空,将收货地下添加为默认收货地址

五、完善显示收货地址页面

  • 点击收货地址页面时,后端就应该将已有收货址信息传递给前端,以供显示

1、后端实现

1.1 展示地址请求方式:

选项 方案
请求方法 POST
请求地址 /users/addresses/

1.2 展示地址请求参数: 无

1.3 展示地址响应结果:HTML,参数

参数为{“addresses”:[address字典,],“default_address_id”:缺省地址id}

1.4 代码实现:

  • 获取当前用户的收货地址列表
  • 循环生成每个地址字典组成的用户地址列表
  • 将用户字典列表与缺省地址组合成参数
  • 返回html和参数
class AddressView(LoginRequiredMixin, View):"""用户收货地址"""def get(self, request):"""提供收货地址界面"""login_user=request.useraddresses=Address.Objects.filter(user=login_user, is_deleted=False)address_list = []for address in addresses:address_dict = {'id': address.id,'title': address.title,'receiver': address.receiver,'province': address.province.name,'city': address.city.name,'district': address.district.name,'place': address.place,'mobile': address.mobile,'tel': address.tel,'email': address.email}address_list.append(address_dict)context = {'addresses': address_list,"default_address_id": request.user.default_address_id if request.user.default_address_id else 0            }return render(request, 'user_center_site.html',context)

2、前端js

  • 将后端模板数据传递到Vue.js
  • /static/js/user_center_site.js
  • /templates/user_center_site.html

3、user_center_site.html中渲染地址信息

<div class="right_content clearfix" v-cloak><div class="site_top_con"><a @click="show_add_site">新增收货地址</a><span>你已创建了<b>[[ addresses.length ]]</b>个收货地址,最多可创建<b>20</b>个</span></div><div class="site_con" v-for="(address, index) in addresses"><div class="site_title"><h3>[[ address.title ]]</h3><a href="javascript:;" class="edit_icon"></a><em v-if="address.id===default_address_id">默认地址</em><span class="del_site">×</span></div><ul class="site_list"><li><span>收货人:</span><b>[[ address.receiver ]]</b></li><li><span>所在地区:</span><b>[[ address.province ]] [[address.city]] [[ address.district ]]</b></li><li><span>地址:</span><b>[[ address.place ]]</b></li><li><span>手机:</span><b>[[ address.mobile ]]</b></li><li><span>固定电话:</span><b>[[ address.tel ]]</b></li><li><span>电子邮箱:</span><b>[[ address.email ]]</b></li></ul><div class="down_btn"><a v-if="address.id!=default_address_id">设为默认</a><a href="javascript:;" class="edit_icon">编辑</a></div></div>
</div>

4、完善user_center_site.js中成功新增地址后的局部刷新

六、编辑收货地址

  • 点击某条收货地址“编辑”按钮时,会显示用户地址修改界面
  • 删除地址后端逻辑和新增地址后端逻辑非常的相似。

1、修改地址接口设计和定义

1.1 修改地址请求方式:

选项 方案
请求方法 PUT
请求地址 /addresses/(?P<address_id>\d+)/

1.2 修改地址请求参数: 路径参数 和 JSON

参数名 类型 是否必传 说明
address_id string 要修改的地址ID(路径参数)
eceiver string 收货人
province_id string 省份ID
city_id string 城市ID
district_id string 区县ID
place string 收货地址
mobile string 手机号
tel string 固定电话
email string 邮箱

1.3 修改地址响应结果:JSON

响应结果 响应内容
code 状态码
errmsg 错误信息
id 地址ID
receiver 收货人
province 省份名称
city 城市名称
district 区县名称
place 收货地址
mobile 手机号
tel 固定电话
email 邮箱

2、后端view实现

  • 判断用户是否登录
  • 接收参数
    • PUT参数存放在request.body中
  • 校验参数
    • 必传参数量否传递
    • 手机号校验
    • 如果填有固定电话,固定电话需要校验
    • 如果填了邮箱,邮箱需校验
  • 更新用户地址
    • 有两种方法:
    • 方法一:Address.objects.get(id=address_id)得到对象,然后依次赋值
    • 方法二:Address.objects.filter(id=address_id).update(参数)
      • 此函数返回值是更新记录的数量,切记
  • 构造响应数据
    • 采用保存方法二时,需要获取修改地址的对象
  • 根据前端需要,返回详细数据
class UpdateDestoryAddressView(LoginRequiredJSONMixin, View):"""更新和删除地址"""def put(self, request, address_id):# 接收参数json_dict = json.loads(request.body.decode())receiver = json_dict.get('receiver')province_id = json_dict.get('province_id')city_id = json_dict.get('city_id')district_id = json_dict.get('district_id')place = json_dict.get('place')mobile = json_dict.get('mobile')tel = json_dict.get('tel')email = json_dict.get('email')# 验证if not all([receiver, province_id, city_id, district_id, place, mobile]):return http.HttpResponseForbidden('缺少必传参数')if not re.match(r"^1[3-9]\d{9}$", mobile):return http.HttpResponseForbidden('参数mobile有误')if tel and not re.match(r'^(0[0-9]{2,3}-)?([2-9][0-9]{6,7})+(-[0-9]{1,4})?$', tel):return http.HttpResponseForbidden('参数固定电话有误')if email and not re.match(r'^[a-z0-9][\w\.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):return http.HttpResponseForbidden('参数email有误')# 更新数据# address = Address.objects.get(id=address_id)# address.title = receiver# address.save()try:# update 返回受影响的行数Address.objects.filter(id=address_id,user=request.user).update(user=request.user,title=receiver,receiver=receiver,province_id=province_id,city_id=city_id,district_id=district_id,place=place,mobile=mobile,tel=tel,email=email,)except Exception as e:return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '修改地址失败'})address = Address.objects.get(id=address_id)address_dict = {'id': address.id,'receiver': address.title,'province': address.province.name,'city': address.city.name,'district': address.district.name,'place': address.place,'mobile': address.mobile,'tel': address.tel,'email': address.email}# 响应新的地址给前端渲染return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '修改地址成功', 'address': address_dict})

3、 路由定义

3、修改地址前端逻辑实现

3.1 添加修改地址的标记

  • 新增地址和修改地址的交互不同。
  • 为了区分用户是新增地址还是修改地址,我们可以选择添加一个变量,作为标记。
  • 为了方便得到正在修改的地址信息,我们可以选择展示地址时对应的序号作为标记。

3.2 实现编辑按钮对应的事件

七、 删除收货地址

  • 本项目采用逻辑删除,所以与修改相似,无需界面

    • 将is_deleted=True即可

1、修改地址接口设计和定义

1.1 修改地址请求方式:

选项 方案
请求方法 DELETE
请求地址 /addresses/(?P<address_id>\d+)/

1.2 修改地址请求参数: 路径参数 和 JSON

参数名 类型 是否必传 说明
address_id string 要修改的地址ID(路径参数)

1.3 修改地址响应结果:JSON

响应结果 响应内容
code 状态码
errmsg 错误信息

2、后端view实现

  • 判断用户是否登录
  • 获取登录用户对象
  • 通过 Address.objects.get(id=address_id) 得到对象,将is_deleted赋值为 True
  • 判断登录用户的缺省地址是否是删除对象
    • 如果是,将登录用户的缺省地址置空
  • 返回前端操作状态
class UpdateDestoryAddressView(LoginRequiredJSONMixin, View):"""更新收获地址"""def delete(self, request, address_id):passdef delete(self, request, address_id):login_user=request.usertry:address=Address.objects.get(id=address_id,user=login_user)address.is_deleted=Trueaddress.save()if login_user.default_address_id==address.id:login_user.default_address=Nonelogin_user.save()except Exception as e:logger.error(e)return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '删除地址失败'})return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '删除地址成功'})

3、路由定义

  • 删除与修改路由一样,只是方法不同,故共用一个路由

4、删除地址前端逻辑实现

  • 后端返回成功后,删除address列表中当前序号的元素

    • this.addresses.splice(起始序号,要删除的项目数量)
  • /static/js/user_center_site.js

八、设置默认地址

1、接口设计和定义

1.1 请求方式:

选项 方案
请求方法 PUT
请求地址 addresses/(?P<address_id>\d+)/default/

1.2 请求参数: 路径参数

参数名 类型 是否必传 说明
address_id string 要修改的地址ID(路径参数)

1.3 响应结果:JSON

响应结果 响应内容
code 状态码
errmsg 错误信息

2、后端view实现

  • 判断用户是否登录
  • 获取登录用户对象
  • 通过 Address.objects.get(id=address_id,user=登录用户) 得到对象
  • 判断登录用户的缺省地址是否是查询到的对象
    • 如果不是,返回数据错误
  • 将查询到的对象赋值给登录用户缺省地址,并保存
  • 返回前端操作结果
class DefaultAddressView(LoginRequiredJSONMixin,View):"""设置默认地址"""def put(self,request,address_id):login_user=request.usertry:address=Address.objects.get(id=address_id,user=login_user)# if not address:#     return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '收货地址数据有误'})login_user.default_address=addresslogin_user.save()except Address.DoesNotExist as e:logger.error(e)return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '设置默认收货地址失败'})return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '设置默认收货地址成功'})

3、路由定义

4、前端逻辑实现

  • 默认地址标识实现方法:
  • 专门定义了一个变量default_address_id,记录默认地址id
  • 每条记录都有一个默认地址标识,只有当此行地址id=default_address_id时,默认地址标只才显示
  • 当默认地址返回正确后,将该记录的地址id 赋值给default_address_id

九、修改地址标题

1、接口设计和定义

1.1 请求方式:

选项 方案
请求方法 PUT
请求地址 addresses/(?P<address_id>\d+)/title/

1.2 请求参数: 路径参数 和 JSON

参数名 类型 是否必传 说明
address_id string 要修改的地址ID(路径参数)
title string 要修改的 title名称

1.3 响应结果:JSON

响应结果 响应内容
code 状态码
errmsg 错误信息

2、后端view实现

  • 判断用户是否登录
  • 获取参数:put 参数在request.body中
    • address_id是路径参数,路由解析得到
    • json_dict=json.loads(request.body.decode())
  • 校验参数
    • 判断 title是否存在
  • 获取登录用户对象
  • 通过 Address.objects.get(id=address_id,user=登录用户) 得到对象
  • 将title的值赋给对象的title,并保存
  • 返回前端操作结果
class TitleAddressView(LoginRequiredJSONMixin,View):"""设置地址标题"""def put(self,request,address_id):login_user=request.userjson_dict=json.loads(request.body.decode())if not json_dict or not json_dict["title"]:return http.HttpResponseForbidden('缺少必传参数')try:address=Address.objects.get(user=login_user,id=address_id)address.title=json_dict["title"]address.save()except Address.DoesNotExist as e:logger.error(e)return http.JsonResponse({'code': RETCODE.DBERR, 'errmsg': '收货地址标题保存失败'})return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '收货地址标题保存成功'})

3、路由定义

4、前端逻辑实现

  • 定义一个变量edit_title_index,用于控制编辑框显示
  • 每个地址信息上方都有编辑框和按钮,只有当edit_title_index=当前idex时,才会显示
    • 当前index是信息大列表中的序号

4.1 用超链接点击事件,显示编辑框及按钮


4.2 编辑框及保存取消按钮显示

4.2 取消和保存处理

Django项目实践(商城):十一、收货地址相关推荐

  1. Django项目(五)收货地址的实现

    一.省市区地址查询 首先分析数据模型类的设计 设计成3张表肯定是不合理的,由于省,市,区具有共性,我们将其设置成一张表 id,name,parent 省的parent设置为null,市的parent设 ...

  2. Django 19购物商城项目(收货地址:添加、修改)

    dDjango 19购物商城项目 1.新建axf_addr,收货地址表 2.路由 3.cart页面,添加默认收货地址 4.视图(主要修改了cart.新建了收货地址相关方法) 5.收货地址列表 6.收货 ...

  3. 设置默认收货地址【项目 商城】

    设置默认收货地址[项目 商城] 设置默认收货地址 1. 持久层 1.1 规划SQL语句 1.2 设计抽象方法 1.3 配置SQL映射 测试 2.业务层 2.1 异常规划 2.2 抽象方法 2.3 实现 ...

  4. DRF 商城项目 - 用户操作(收藏, 留言, 收货地址)

    个人收藏 整体逻辑类似于 个人中心 ( 个人中心的相关逻辑梳理详情  点击这里 ) 也是两个序列化组价的分流 查看收藏  ( list ) 详情指向 收藏详情 的组价 创建收藏 ( create ) ...

  5. 39 Flutter仿京东商城项目 收货地址列表、增加 修改收货地址布局、弹出省市区选择器...

    加群452892873 下载对应39课文件,运行方法,建好项目,直接替换lib目录 pubspec.yaml city_pickers: ^0.1.22 AddressAdd.dart import ...

  6. 美多商城之用户中心(收货地址1)

    三.收货地址 用户地址的主要业务逻辑有: 展示省市区数据 用户地址的增删改查处理 设置默认地址 设置地址标题 3.1 省市区三级联动 1. 展示收货地址界面 提示: 省市区数据是在收货地址界面展示的, ...

  7. web电商、商城pc端、商城、购物车、订单、线上支付、web商城、pc商城、登录注册、人工客服、收货地址、现金券、优惠券、礼品卡、团购订单、评价晒单、消息通知、电子产品商城、手机商城、电脑商城

    web电商.商城pc端.商城.购物车.订单.线上支付.web商城.pc商城.登录注册.人工客服.收货地址.现金券.优惠券.礼品卡.团购订单.评价晒单.消息通知.电子产品商城.手机商城.电脑商城 Axu ...

  8. UNIAPP实战项目笔记43 购物车页面修改收货地址和修改默认地址

    UNIAPP实战项目笔记43 购物车页面修改收货地址和修改默认地址 实际案例图片 修改收货地址和修改默认地址页面布局和功能 具体内容图片自己替换哈,随便找了个图片的做示例 用到了vuex的状态机,具体 ...

  9. php商城手机端省市显示,jQuery仿手机京东商城收货地址城市选择

    jQuery仿手机京东商城收货地址城市选择 js代码 /** * 默认调用 */ !function () { var $target = $('#J_Address'); $target.cityS ...

最新文章

  1. 网站设计支离破碎:究竟是谁之过
  2. VC中CListCtrl中的LVCOLUMN和LVITEM详细介绍
  3. 【PAT乙级】1009 说反话 (20 分)
  4. ViewModelBase ObservableObject
  5. Canvas绘制星球轨迹移动
  6. 如何在 SAP 电商云 Spartacus UI 里新建一个页面
  7. 6. 堪比JMeter的.Net压测工具 - Crank 实战篇 - 收集诊断跟踪信息与如何分析瓶颈
  8. 从头编写 asp.net core 2.0 web api 基础框架 (2)
  9. 论文写作思路_2018年的16个写作思路
  10. div+css 固定宽度且居中 文字左对齐
  11. 利用VS2010进行SQL Server服务器和本地的数据融合
  12. 数学模型的相关概念及意义等理论内容
  13. SPSS实战:单因素方差分析(ANOVA)
  14. ecshop模板支持php,ecshop模板支持php数据运算的代码实例
  15. 7-10 学生成绩排序 (15 分)
  16. 网页视频倍速播放的方法
  17. ffmpeg截取视频内容和批量处理视频
  18. 竟然如愿让我拿到诸多大厂offer(头条,PDD,Alibaba)-来自Alibaba的Java面试指南,
  19. moodle 1.9 课程 恢复 2.0
  20. 安卓(android)6.0高通平台下设备树专题视频讲解【全国独家+设备树视频教程】

热门文章

  1. java jdk安装失败 mac_Mac环境下JDK安装方法
  2. ASP.NET债务管理系统源码
  3. MySQL MySQL进阶路:从小工到专家的必读书籍和必备工具
  4. Jflash 命令行 烧录程序 注意事项
  5. 英飞凌ADS编译器汉化
  6. java web网上商城项目实战与源码
  7. Linux编译时如何减小so库文件的大小
  8. Dialog(对话框窗口)
  9. 非常好用的有道词典 For Alfred
  10. jQuery入门jQuery API-1