前端学习案例-一文带你理解如何解决工作中的需求

简介: 前端学习案例-一文带你理解如何解决工作中的需求
我是歌谣 放弃很容易 但是坚持一定很酷
1前言
    在我们的开发过程中 会遇到一些开发的需求 怎么实现 怎么写 怎么做才最合理
2需求处理
    拿到一个需求就和做数学题一样 我们要理清所有的关系 由于本文知识对需求进行阐述 所以就以vue为例子
2.1 需求1处理页面样式某页面跳转之后如果传过去的值为1则显示我是歌谣 如果传过去的值是2则显示我是帅气的歌谣
    就眼前的问题 你可能就会陷入一个深深的思考 页面怎么传值呢 怎么传呢 我可以进行路由拼接传参 也可以引入第三方插件存储到storage传参 我可以vuex传参那么什么样才是最优解呢
    本文旨在说明需求如何实现 我拿出其中一种 我采用第三方插件传参
 2.1.1第一步 npm install 一下
npm install store2
2.1.2第二步 封装好插件
    封装get 存储等方法即可
2.1.3页面引入
import Storage from 'xxxx'
2.1.4页面调用
    xxx.session()
     xxx.get()    到了这边 页面相互传值的事情就搞定了 但是这是一种比较好的选择吗 他已经实现了
 2.2 需求1处理页面样式某页面跳转之后如果传过去的值为1则显示我是歌谣 如果传过去的值是2则显示我是帅气的歌谣
    此时我们页面的传值已经搞定了 但是这个值过来了以后呢 怎么去做一个判断显示 我可以直接v-if判断 也可以v-if v-else判断 也可以v-show去实现 但是最后你选择如何实现是你自己去想呢
  2.2.1第一步 我们直接写样式
     <div v-if="this.instanceType === 0" class="title-right">
               我是歌谣
               </div>
               <template v-else>
                 <div class="progress-panel">
                我是帅气的歌谣
                 </div>
               </template>    值已经过来了 我做了一个判断 但是这样的方式是一个最优解吗 上面的方式有很多 我为什么要采用这种
 2.3需求2新建任务页面和编辑页面用的同一个表单 我们如何实现
    同样实现这个页面逻辑的方法有很多种 你可以不嫌麻烦 直接多写结构页面
    也可以单独去编写一个页面去进行一个页面的布局 当页面值新建去给与 一个状态 页面编辑的时候给与另外一个状态
2.3.1页面代码
    <!--控制部门管理的页面-->
     <template>
       <div class="table-list-page">
         <div class="query-area">
         <div class="operation-button-area">
           <!--点击按钮-->
           <el-button icon="el-icon-plus" style="float: right;margin-right: 20px;margin-bottom: 20px" size="medium" type="primary" @click="handleAdd">
             新建账户
           </el-button>
         </div>
         </div>
         <div>
           <custom-table    v-loading="loading"
                            element-loading-text="拼命加载中"
                            element-loading-spinner="el-icon-loading" element-loading-background="rgba(0, 0, 0, 0.8)" @size-changes="list"  @pagination-change="list" :data="tableData" :columns="columns" :pagination="pagination">
             <template v-slot:action>
               <el-table-column fixed="right" label="操作">
                 <template slot-scope="scope">
                   <el-button @click="handleEdit(scope.row)" type="text">
                     编辑
                   </el-button>
                   <el-button type="text" @click="deleteRecord(scope.row)">
                     删除
                   </el-button>
                   <!--绑定数据使用当前的id-->
                   <el-button type="text" @click="BindAccount(scope.row)">
                     绑定
                   </el-button>
                 </template>
               </el-table-column>
             </template>
           </custom-table>
         </div>
         <create ref="create" @ok="list"/>
         <account-bind ref="list"></account-bind>
       </div>
     </template>
     <script>
     import AccountBind from "@/views/system/account/AccountBind";
     import Create from "./create";
     import CustomTable from "@/component/table/CustomTable";
     import {TableListMixin} from "@/component/table/TableMixin";
     import {getAction, putAction} from "@/api";
     export default {
       name: "Account",
       mixins: [TableListMixin],
       components: {
         CustomTable,
         Create,
         AccountBind
       },
       inject:['reload'],
       data() {
         return {
           value:'',
           columns: [
          /*   {type: "selection", width: "50"},*/
             {prop: "id", label: "ID", width: "60", sortable: true},
             {prop: "name", label: "账号名称", width: "100", sortable: true},
             {prop: "department_name", label: "所属部门",sortable: true},
             {prop: "platform", label: "所属平台",sortable: true},
             {prop: "content_type", label: "内容类型",sortable: true},
             {prop: "resource_type", label: "资源类型",sortable: true},
             {prop: "price", label: "刊例价",sortable: true}
           ],
           url: {
             list: "/account",
             delete: "/account",
           },
           tableData:[],
           departmentList:[],
         /*存储部门*/
           form:{
           }
         };
       },
       computed: {
         DepartmentId(){
           return this.$store.state.department.id
         },
       },
       methods: {
         ListSeach(){
           getAction("/account",{
             page:1,
             limit:10,
             department_id:this.query.type
           }).then(res=>{
             console.log(res)
           })
         },
         BindAccount(record){
           this.$refs["list"].show(record)
         }
       }
     };
     </script>
     <style lang="scss" scoped>
     .left-right {
       margin-left: 100px;
     }
     .el-table th, .el-table td {
       text-align: center;
     }
     @import "@/assets/style/table";
     </style>        submit() {
           this.$refs["form"].validate(valid => {
             if (valid) {
               setTimeout(() => {
                 /*声明变量*/
                 let method = postAction;
                 /*声明url
                 * position()
                 * */
                 /*url=/user*/
                 let url = this.url.add;
                 /*4 判断是否有id 确定新增还是编辑  根据表单数据是否有 id 属性,判断是新增还是编辑操作
                   // 如果有id的话 就需要进行*/
                 if (this.form.id) {
                   method = putAction;
                   /*编辑操作 /user*/
                   url = path.join(this.url.edit, this.form.id);
                 }
                 /*如果没有请求地址 就做出判断*/
                 if (!url) {
                   this.$message.warning("请设定请求 url!");
                   return;
                 }
                 /*5GY 通过这边取触发父亲级别的方法*/
                 method(url, this.form).then(res => {
                   if(res.code==0) {
                     /*实现文字居中逻辑<div style=";"><p style="display:flex;font-weight: bold;text-align: center;*/
                     this.$message.success({
                       dangerouslyUseHTMLString: true,
                       message: '<p>提交成功</p>'
                     });
                     this.$emit("ok");
                     this.$refs["form"].resetFields()
                     this.close();
                   }
                 });
               }, 400);
             }else {
               setTimeout(() => {
                 this.$message("请您按照要求填写信息")
                 this.$refs["form"].resetFields()
                 return false;
               }, 400);
             }
           });
         },    简单介绍一下逻辑 由于是element的dialog分别作出的一个文件的一个判断 编辑和新建 主要的区别是看是否存在一个id 如果页面传值的时候获取到了当前的一个id就进行了一个编辑的操作
    反之就是一个新建的操作 同时根据页面实现了一个不同的页面展示和页面提示 此处又要思考为什么要这样实现了 他是最优解吗
  2.4需求3 如果一个平台的分发对应着不同的渠道 不同的渠道又是对应这不同的输入渲染框
    曾几何时 我做这块的需求就进行了一个面向过程编程
       //处理当前数据是今日头条的数据逻辑
           if(this.info.account.plugin_name=='今日头条') {
             /*判断原创内容的数值不能为空 如果数值为空 就给与一个默认值false*/
             if (!this.form.hasOwnProperty('original')) {
               /*我们就给与她一个数值设置为false*/
               this.form.original = false
             }
             /*判断赞赏的数据数值是否为空 如果是空就给与他一个默认值*/
             if (!this.form.hasOwnProperty('xigua_praise')) {
               /*我们就给与她一个数值设置为false*/
               this.form.xigua_praise = false
             }
             /*判断视频封面的值属性是否存在 如果不存在就给予一个默认值0*/
             if (!this.form.hasOwnProperty('xigua_video_face')) {
               /*我们就给与她一个数值设置为false*/
               this.form.xigua_video_face = 0
             }
             /*判断项目名不能为空*/
             if(this.project_name==''){
               this.$message("项目名不能为空")
               return false
             }
             /*今日头条上传数据编写*/
             /*判断当前数据中是否含有名称这个属性 有的话*/
             if (this.form.hasOwnProperty('name')) {
               /*如果有的话 开始对字符串的长度进行判断 利用替代修改中文长度计数为2 */
               if (this.form.name.replace(/[^\x00-\xff]/g, "a").length < 5 || this.form.name.replace(/[^\x00-\xff]/g, "a").length > 50) {
                 this.$message("请控制名称在五个字符和三十个字符之间当前输入值为" + this.form.name.replace(/[^\x00-\xff]/g, "a").length + "个字符")
                 return false
               }
             }
             /*判断简介的数据是否满足规范*/
             if (!this.form.hasOwnProperty('intro')) {
               this.$message("简介项的值不能为空")
               return false
               /*如果有的话 开始对字符串的长度进行判断 利用替代修改中文长度计数为2 */
             } else {
               /*控制数值不能大于四百*/
               if (this.form.intro.replace(/[^\x00-\xff]/g, "a").length > 400) {
                 this.$message("简介项输入的值在(400以内)")
                 return false
               }
             }
             /*修改完成头条小视频的数据权限*/
           }else if(this.info.account.plugin_name=='头条小视频'){
             /*判断项目名不能为空*/
             if(this.project_name==''){
               this.$message("项目名不能为空")
               return false
             }
             if (this.form.hasOwnProperty('name')) {
               /*判断里面是否又name属性 */
               if (this.form.name.replace(/[^\x00-\xff]/g, "a").length < 11 || this.form.name.replace(/[^\x00-\xff]/g, "a").length > 30) {
                 this.$message("请填写名称(11-30个字符)")
                 return false
               }
             }
             /*判断当前的数据来bilibili*/
           }else if(this.info.account.plugin_name=='Bilibili'){
             /*判断项目名不能为空*/
             if(this.project_name==''){
               this.$message("项目名不能为空")
               return false
             }
             console.log(this.form,"1312312312312")
             /*判断名称的字符是否存在*/
             if (this.form.hasOwnProperty('name')) {
               /*判断里面是否又name属性 */
               if (this.form.name.replace(/[^\x00-\xff]/g, "a").length < 1 || this.form.name.replace(/[^\x00-\xff]/g, "a").length > 80) {
                 this.$message("请填写名称(1-80个字符)")
                 return false
               }
             }
               /*判断标签值不能为空*/
               if (!this.form.hasOwnProperty('tag')) {
                 /*我们就给与她一个数值设置为false*/
                /*this.$message("话题和标签值不能为空")*/
                 /*判断长度为0的时候标签值为空*/
               }else{
                 if(this.form.tag.length==0){
                   this.$message("话题和标签值不能为空")
                 }
               }
               /*判断分类不能为空*/
               if (!this.form.hasOwnProperty('category')) {
                 this.$message("分类的值不能为空")
               }else{
                 if( this.form.category.length==0){
                   this.$message("分类的值不能为空")
                 }
               }
               /*判断原创内容的数值不能为空 如果数值为空 就给与一个默认值false*/
               if (!this.form.hasOwnProperty('original')) {
                 /*我们就给与她一个数值设置为false*/
                 this.form.original = false
               }
               /*判断视频栏目不能为空*/
               if (!this.form.hasOwnProperty('upload-image')) {
                 /*我们就给与她一个数值设置为false*/
                 this.$message("视频封面不能为空")
               }
     /*判断快手视频的数据格式*/
           }else if(this.info.account.plugin_name=='快手视频'){
             /*判断项目名不能为空*/
             if(this.project_name==''){
               this.$message("项目名不能为空")
               return false
             }
             /*判断名称的字符是否存在*/
             if (this.form.name=='') {
               /*判断里面是否又name属性 */
               this.$message("名称不能为空")
               return false
               if (this.form.name.replace(/[^\x00-\xff]/g, "a").length > 500) {
                 this.$message("请填写名称(500个字符以内)")
                 return false
               }
             }
             /*判断视频栏目不能为空*/
             if (!this.form.hasOwnProperty('upload-image')) {
               /*我们就给与她一个数值设置为false*/
               this.$message("视频封面不能为空")
               return false
             }
           }else if(this.info.account.plugin_name=='百家号'){
             /*判断原创内容的数值不能为空 如果数值为空 就给与一个默认值false*/
             if (!this.form.hasOwnProperty('original')) {
               /*我们就给与她一个数值设置为false*/
               this.form.original = false
             }
             /*判断项目名不能为空*/
             if(this.project_name==''){
               this.$message("项目名不能为空")
               return false
             }
             /*判断名称的字符是否存在*/
             if (this.form.hasOwnProperty('name')) {
               /*判断里面是否又name属性 */
               if (this.form.name.replace(/[^\x00-\xff]/g, "a").length <9||this.form.name.replace(/[^\x00-\xff]/g, "a").length > 40) {
                 this.$message("请填写名称(9-40个字符)")
                 return false
               }
             }
             /*判断视频栏目不能为空*/
             if (!this.form.hasOwnProperty('upload-image')) {
               /*我们就给与她一个数值设置为false*/
               this.$message("视频封面不能为空")
               return false
             }
           }else if(this.info.account.plugin_name=='抖音短视频'){
             /*判断项目名不能为空*/
             if(this.project_name==''){
               this.$message("项目名不能为空")
               return false
             }
             /*判断名称的字符是否存在*/
             if (this.form.hasOwnProperty('name')) {
               /*判断里面是否又name属性 */
               if (this.form.name.length ==0) {
                 this.$message("请保证输入名称的值不为空")
               }
             }
             /*判断视频封面的值属性是否存在 如果不存在就给予一个默认值0*/
             if (!this.form.hasOwnProperty('awemepro_video_face')) {
               /*我们就给与她一个数值设置为false*/
               this.form.awemepro_video_face = 0
             }
           }else if(this.info.account.plugin_name=='微信视频号'){
             /*判断项目名不能为空*/
             if(this.project_name==''){
               this.$message("项目名不能为空")
               return false
             }
             console.log(11111)
             /*判断名称的字符是否存在*/
             if (this.form.hasOwnProperty('name')) {
               /*判断里面是否又name属性 */
               if (this.form.name=="") {
                 this.$message("请保证输入名称的值不为空")
                 return false
               }
             }
             /*判断视频栏目不能为空*/
             if (!this.form.hasOwnProperty('upload-image')) {
               /*我们就给与她一个数值设置为false*/
               this.$message("视频封面不能为空")
             }
             if (!this.form.hasOwnProperty('wxvideo_videocut')) {
               /*我们就给与她一个数值设置为false*/
               this.$message("视频裁剪值不能为空")
             }
           }     这种编程有什么坏处呢 首先他就是再加入一个新的渠道的时候就会要加入很多种东西 不利于代码的自身维护和更新迭代 这是比较麻烦的一件事件 所以说 处理一个需求需要一个完整的思路和思想
    紧接着我就开始了面向对象编程 对 是对象 你有对象吗 有就挺好
    // 规则
           const rules = this.rules1;
           // 需要被遍历的值
           const targets = this.AweMepro;
           // 表单
           const form = this.form;
           console.log(this.form.project_name,"191991")
           if(typeof(this.form.project_name)=='undefined'||this.form.project_name==null||this.form.project_name==''){
             this.$message("项目名不能为空")
             return false
           }
           for (let rule in rules) {
             for (let target in targets) {
               if (rule == targets[target].key) {
                 /*如果封面的赞赏为空 就给他一个默认值*/
                 if(rule=="xigua_praise"){
                   form[targets[target].key]=false
                   continue
                   /*if (typeof (form[targets[target].key]) == 'undefined' || form[targets[target].key] == null || form[targets[target].key] == '') {
                     this.$message("封面不能为空")
                     return false
                   }*/
                 }
                 /*如果封面的内容为空 就给他一个默认值*/
                 console.log(form[targets[target].key],"0000")
                 if(rule=="awemepro_video_face"){
                   form[targets[target].key]=0
                   continue
                   /*if (typeof (form[targets[target].key]) == 'undefined' || form[targets[target].key] == null || form[targets[target].key] == '') {
                     this.$message("封面不能为空")
                     return false
                   }*/
                 }
                 if(rule=="xigua_video_face"){
                   form[targets[target].key]=0
                   continue
                   /*if (typeof (form[targets[target].key]) == 'undefined' || form[targets[target].key] == null || form[targets[target].key] == '') {
                     this.$message("封面不能为空")
                     return false
                   }*/
                 }
                 /*原创内容*/
                 if(rule=="original"){
                   form[targets[target].key]=false
                   continue;
                 }
                 /*如果原创的内容为空 就给与他一个默认值*/
                 if (rule == "name") {
                   let size = 0;
                   /*最外层的赋值不可修改 判断长度控制命名不同值*/
                   let max = rules[rule].max_length;
                   let min = rules[rule].min_length
                   if (max == 0 && min == 0) {
                     if (typeof (form[targets[target].key]) == 'undefined' || form[targets[target].key] == null || form[targets[target].key] == '') {
                       this.$message("名称不能为空")
                       return false
                     }
                     continue
                     /*反之验证*/
                   } else {
                     if (typeof (form[targets[target].key]) == "string") {
                       size = form[targets[target].key].replace(/[^\x00-\xff]/g, "a").length;
                     }
                     if (size < min || size > max) {
                       /*console.log(form[targets[target].key].length);*/
                       /*console.log(typeof form[targets[target].key] == "array");*/
                       this.$message(targets[target].name + "不能为空, 请输入(" + min + "-" + max + "个字符)")
                       return false;
                     }
                   }
                 }
                 /*判断标签的数值不能为空 如果是满足就继续执行*/
                 if (rule == "tags"){
                   /*如果标签值是 00 就不用验证*/
                   let max = rules[rule].max_length;
                   let min =  rules[rule].min_length
                   if(max==0&&min==0){
                     continue
                     /*反之验证*/
                   }else{
                     if (form[targets[target].key].length==0){
                       this.$message(targets[target].name + "不能为空")
                     }else{
                       let ArrTags=form[targets[target].key]
                       for(var Arr in ArrTags){
                         console.log(ArrTags[Arr])
                         let size = 0;
                         if (typeof (ArrTags[Arr]) == "string"){
                           size = ArrTags[Arr].replace(/[^\x00-\xff]/g, "a").length;
                         }
                         if (size < min || size > max) {
                           /*console.log(form[targets[target].key].length);*/
                           /*console.log(typeof form[targets[target].key] == "array");*/
                           this.$message(targets[target].name +"需要输入"+"(" + min + "-" + max + "个字符)")
                           return false;
                         }
                       }
                     }
                   }
                 }
                 /*如果是分类*/
                 if(rule=="category"){
                   console.log(form[targets[target].key],"9999")
                   /*     console.log(form[targets[target].key].length)*/
                   if(typeof(form[targets[target].key])=='undefined'){
                     this.$message(targets[target].name + "不能为空")
                     return  false
                   }
                 }
                 /*判断封面的地址上传数据不能为空 如果不是为空 就可以继续执行*/
                 if (rule == "upload-image"){
                   if (form[targets[target].key] != null) {
                     continue;
                   }
                 }
                 /*如果是转载描述*/
                 if(rule=="trans_reason"){
                   form[targets[target].key]=null
                   continue;
                 }
                 if(rule=="intro") {
                   if (typeof (form[targets[target].key]) == 'undefined' || form[targets[target].key] == null || form[targets[target].key] == '') {
                     this.$message(targets[target].name + "不能为空")
                     return false
                   }
                 }
                 if(rule=="wxvideo_videocut"){
                   if (typeof (form[targets[target].key]) == 'undefined' || form[targets[target].key] == null || form[targets[target].key] == '') {
                     this.$message(targets[target].name+"不能为空")
                     return false
                   }
                   let size = 0;
                   if (typeof (form[targets[target].key]) == "string"){
                     size = form[targets[target].key].replace(/[^\x00-\xff]/g, "a").length;
                   }
                   let max = rules[rule].max_length;
                   let min =  rules[rule].min_length
                   if (size < min || size > max) {
                     this.$message(targets[target].name + "不能为空, 请输入(" + min + "-" + max + "个字符)")
                     return false;
                   }
                 }  2.5需求4 如何实现一个一键复制的功能 需求就是有一段文字 给个按钮 点击复制 他就能到处粘贴了
    看见这个需求我一开始发现就是蒙圈的
  2.5.1如何搭建一个完整的前端页面架构    你需要做的事 整体的架构按照特定的规则进行编写
    比如我的页面的整体布局全部按照这个架构编写 其余的样式只要塞进去作为样式进行逐步布局即可
 2.6.1更多需求.......
 3总结    在我们日常的开发中 会遇到各种各样的需求
    1首先我们要明确我们需要实现的是什么
    2再之后我们需要理解这个需求实现的方法有哪些
    3这些方法的步骤是怎么样的
    4什么才是方法的最优解
    需求是做不完的 而我们要不断去理解一些新知识点 找到一些最优解决方案 不断提升自己 我是歌谣 放弃很容易但是坚持一定很酷
相关文章
|
2月前
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
56 0
|
1月前
|
前端开发 开发者 C++
独家揭秘:前端大牛们如何高效学习新技术,保持竞争力!
【10月更文挑战第31天】前端技术飞速发展,如何高效学习新技术成为关键。本文通过对比普通开发者与大牛们的策略,揭示了高效学习的秘诀:明确目标、主动探索、系统资源、实践应用和持续学习。通过这些方法,大牛们能更好地掌握新技术,保持竞争力。示例代码展示了如何通过实践加深理解。
50 4
|
3月前
|
前端开发 JavaScript
前端一键回到顶部案例
本文介绍了如何实现网页中的一键回到顶部功能,包括两种方法:第一种是通过HTML中的锚点跳转实现快速回到顶部;第二种是使用JavaScript的`scrollTo`方法结合`requestAnimationFrame`实现滚动动画效果,让页面滚动更加平滑自然。
66 1
前端一键回到顶部案例
|
2月前
|
JavaScript 前端开发 Java
VUE学习四:前端模块化,ES6和ES5如何实现模块化
这篇文章介绍了前端模块化的概念,以及如何在ES6和ES5中实现模块化,包括ES6模块化的基本用法、默认导出与混合导出、重命名export和import,以及ES6之前如何通过函数闭包和CommonJS规范实现模块化。
127 0
VUE学习四:前端模块化,ES6和ES5如何实现模块化
|
2月前
|
前端开发 JavaScript 小程序
前端新机遇!为什么我建议学习鸿蒙?
【10月更文挑战第4天】前端新机遇!为什么我建议学习鸿蒙?
130 0
前端新机遇!为什么我建议学习鸿蒙?
|
3月前
|
前端开发 数据安全/隐私保护
【前端web入门第二天】03 表单-下拉菜单 文本域 label标签 按钮 【附注册信息综合案例】
本文档详细介绍了HTML表单的多种元素及其用法,包括下拉菜单(`&lt;select&gt;` 和 `&lt;option&gt;`)、文本域(`&lt;textarea&gt;`)、标签解释(`&lt;label&gt;`)、各类按钮(`&lt;button&gt;`)及表单重置功能、无语义布局标签(`&lt;div&gt;` 和 `&lt;span&gt;`)以及字符实体的应用。此外,还提供了一个完整的注册信息表单案例,涵盖个人信息、教育经历和工作经历等部分,展示了如何综合运用上述元素构建实用的表单。
【前端web入门第二天】03 表单-下拉菜单 文本域 label标签 按钮 【附注册信息综合案例】
|
2月前
|
存储 前端开发 Java
验证码案例 —— Kaptcha 插件介绍 后端生成验证码,前端展示并进行session验证(带完整前后端源码)
本文介绍了使用Kaptcha插件在SpringBoot项目中实现验证码的生成和验证,包括后端生成验证码、前端展示以及通过session进行验证码校验的完整前后端代码和配置过程。
313 0
验证码案例 —— Kaptcha 插件介绍 后端生成验证码,前端展示并进行session验证(带完整前后端源码)
|
3月前
|
JavaScript 前端开发
前端基础(十)_Dom自定义属性(带案例)
本文介绍了DOM自定义属性的概念和使用方法,并通过案例展示了如何使用自定义属性来控制多个列表项点击变色的独立状态。
54 0
前端基础(十)_Dom自定义属性(带案例)
|
3月前
|
JSON 前端开发 JavaScript
socket.io即时通信前端配合Node案例
本文介绍了如何使用socket.io库在Node.js环境下实现一个简单的即时通信前端配合案例,包括了服务端和客户端的代码实现,以及如何通过socket.io进行事件的发送和监听来实现实时通信。
58 2
|
3月前
|
前端开发
【前端web入门第五天】03 清除默认样式与外边距问题【附综合案例产品卡片与新闻列表】
本文档详细介绍了CSS中清除默认样式的方法,包括清除内外边距、列表项目符号等;探讨了外边距的合并与塌陷问题及其解决策略;讲解了行内元素垂直边距的处理技巧;并介绍了圆角与盒子阴影效果的实现方法。最后通过产品卡片和新闻列表两个综合案例,展示了所学知识的实际应用。
78 11