精华内容
下载资源
问答
  • 2018-05-30 14:10:30

    介绍这三个组件:

    菜单栏组件JMenuBar:该组件可以添加菜单,添加的菜单会排成一行。

    菜单栏JMenu:可以显示的一个个的菜单,该组件可以添加子菜单,也可以添加菜单,添加的菜单会排成一列。

    子菜单JMnuItem:可以添加到菜单中。

    其实这个三个组件还是有点绕人的,但是大家做一遍就理解了,光看不容易懂。


    如何创建组件:

    JMenuBar name=new JMenuBar();    //创建菜单栏
    JMenu name=new JMenu("");     //创建菜单
    JMenuItem name=new JMenuItem("");    //创建子菜单

    代码实现:

    import java.awt.*;
    import javax.swing.*;
    public class Swing_JMenu extends JFrame{
    
    	//定义组件
    	JMenuBar jmb;	//定义菜单栏
    	JMenu jm1,jm2,jm3,jm4,jm5;	//定义菜单
    	JMenu jm6,jm7,jm8,jm9;		//定义菜单中的菜单
    	JMenuItem jmi1,jmi2,jmi3,jmi4,jmi5;		//定义子菜单
    	public static void main(String[] args) {
    		Swing_JMenu a=new Swing_JMenu();
    
    	}
    	public Swing_JMenu()
    	{
    		//创建组件
    		jmb=new JMenuBar();		//创建菜单栏
    		jm1=new JMenu("文件");	//创建菜单
    		jm2=new JMenu("编辑");
    		jm3=new JMenu("资源");
    		jm4=new JMenu("窗口");
    		jm5=new JMenu("帮助");
    		jm6=new JMenu("新建");
    		jm7=new JMenu("打开");
    		jm8=new JMenu("保存");
    		jm9=new JMenu("导入");
    		jmi1=new JMenuItem("文档");	//创建子菜单
    		jmi2=new JMenuItem("工程");
    		jmi3=new JMenuItem("包");
    		jmi4=new JMenuItem("类");
    		jmi5=new JMenuItem("接口");
    		
    		//设置布局管理器
    		
    		//添加组件
    		jm6.add(jmi1);	//把子菜单添加到菜单中
    		jm6.add(jmi2);
    		jm6.add(jmi3);
    		jm6.add(jmi4);
    		jm6.add(jmi5);
    		
    		jm1.add(jm6);	//把菜单添加到菜单中
    		jm1.add(jm7);
    		jm1.add(jm8);
    		jm1.add(jm9);
    		
    		jmb.add(jm1);	//把菜单添加到菜单栏中
    		jmb.add(jm2);
    		jmb.add(jm3);
    		jmb.add(jm4);
    		jmb.add(jm5);
    		
    		this.add(jmb,BorderLayout.NORTH);	//把菜单栏添加到框架北部
    		
    		//设置界面属性
    		this.setTitle("菜单栏案例");		//设置界面标题
    		this.setSize(300, 250);				//设置界面像素
    		this.setLocation(200, 200);			//设置界面初始位置
    		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);	//设置虚拟机和界面一同关闭
    		this.setVisible(true);				//设置界面可视化
    	}
    }
    

    常用方法:

    setMnemonic('快捷键') //设置一个快捷键,按住alt+快捷键可以快捷点击


    欢迎各位在评论区留言探讨~~


    更多相关内容
  • 创建和添加下拉式菜单,分为以下三个步骤 1.创建一个JMenuBar菜单栏对象,将其放置在JFrame窗口的顶部 2.创建JMenu菜单对象,将其添加到JMenuBar菜单中 3.创建JMenuItem菜单项,将其添加到JMenu菜单中 package ...

    创建和添加下拉式菜单,分为以下三个步骤

    1.创建一个JMenuBar菜单栏对象,将其放置在JFrame窗口的顶部

    2.创建JMenu菜单对象,将其添加到JMenuBar菜单中

    3.创建JMenuItem菜单项,将其添加到JMenu菜单中

    package gui;

    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;

    import javax.swing.JDialog;
    import javax.swing.JFrame;
    import javax.swing.JMenu;
    import javax.swing.JMenuBar;
    import javax.swing.JMenuItem;

    public class T15 {
        public static void main(String[] args) {
            JFrame j = new JFrame("下拉式菜单");//创建窗体,名称为下拉式菜单
            JMenuBar mb = new JMenuBar();//创建菜单栏
            JMenu menu = new JMenu("操作");//创建菜单名称为操作
            JMenuItem item1 = new JMenuItem("弹出窗口");//创建菜单项名称为弹出窗口
            JMenuItem item2 = new JMenuItem("关闭");//创建菜单项名称为关闭
    //        为菜单项item1添加事件监听器
            item1.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
    //                创建一个JDialog窗体
                    JDialog dialog = new JDialog(j,true);
                    dialog.setTitle("弹出窗口");
                    dialog.setSize(200,200);
                    dialog.setLocation(50, 50);
                    dialog.setVisible(true);
                }
            });
    //        为菜单项item2添加事件监听器
            item2.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
    //                退出
                    System.exit(0);
                }
            });
            
            menu.add(item1);//将菜单项添加到菜单中
            menu.add(item2);//将菜单项添加到菜单中
            mb.add(menu);//将菜单操作添加到菜单栏
            j.setJMenuBar(mb);//将菜单栏添加到JFrame窗体中
            
            j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            j.setSize(300,300);//设置窗体大小为宽300,高300
            j.setVisible(true);//设置窗体可见
        }
        
    }

    下面写弹出式菜单

    在windows桌面单击鼠标右键会出现一个菜单,那就是弹出式菜单。

    在JAVA中的Swing组件中,弹出式菜单用JPopupMenu表示

    package gui;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;

    import javax.swing.JFrame;
    import javax.swing.JMenuItem;
    import javax.swing.JPopupMenu;
    public class T16 {
        public static void main(String[] args) {
            JFrame j = new JFrame("弹出式菜单");
    //        创建一个JPopupMenu菜单
            JPopupMenu jpm = new JPopupMenu();
    //        创建三个JMenuItem菜单项
            JMenuItem item1 = new JMenuItem("refresh");
            JMenuItem item2 = new JMenuItem("create");
            JMenuItem item3 = new JMenuItem("exit");
    //        为exit添加监听器
            item3.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    System.exit(0);
                }
            });
    //        往JPopupMenu菜单添加菜单项
            jpm.add(item1);
            jpm.add(item2);
            jpm.addSeparator();//添加水平分割线
            jpm.add(item3);
    //        为JFrame窗口添加鼠标clicked事件监听器
            j.addMouseListener(new MouseAdapter() {
                public void mouseClicked(MouseEvent e) {
    //                如果单击的是鼠标的右键,显示JPopupMenu菜单
                    if(e.getButton()==e.BUTTON3) {
                        jpm.show(e.getComponent(),e.getX(),e.getY());
                    }
                }
            });
            j.setSize(300,300);
            j.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            j.setVisible(true);
        }
    }

     

     

    展开全文
  • 前端组件化开发实践总结

    千次阅读 多人点赞 2021-10-13 12:46:52
    自从 2010 年第一份工作接触了前后端半分离的开发方式之后,在后面的这些年里,对前端的组件化开发有了更全面一点的认识,组件化在我们的前端开发中,对提高开发效率、代码的可维护性和可复用性有很大帮助,甚至对跟...

    自从 2010 年第一份工作接触了前后端半分离的开发方式之后,在后面的这些年里,对前端的组件化开发有了更全面一点的认识,组件化在我们的前端开发中,对提高开发效率、代码的可维护性和可复用性有很大帮助,甚至对跟设计师沟通的效率和企业的品牌形象都有着深刻的影响。这篇文章就把我在开发中总结的一些组件化开发经验分享一下。示例中的所有代码都是伪代码,你可以按照实际情况应用到 React 或 Vue 的项目中。

    前端组件化发展历史

    在讨论组件化开发之前,我们先看看前端组件化开发的发展历史。网页开发刚起步时,并没有『前端』这个概念,更不用提组件化了。当时,网页只是作为可以在浏览器中浏览的富文本文件,开发网页就是使用一些标签让浏览器解析并显示。受制于 HTML 只是描述式的语言,网页中的代码没有办法复用,即使是类似的页面,都需要复制粘贴大量的重复代码:

    <!-- index.html -->
    <nav>
      <!-- 导航 -->
    </nav>
    <main>
      <!-- 内容 -->
    </main>
    <footer>
      <!-- 页脚 -->
    </footer>
    
    <!-- blogPost.html -->
    <nav>
      <!-- 相同的导航 -->
    </nav>
    <main>
      <!-- 不同的内容 -->
    </main>
    <footer>
      <!-- 相同的页脚 -->
    </footer>
    

    后来随着模板引擎的出现,可以把网页的代码分割成片段(Fragments)或模板(Templates),例如导航,内容,页脚等等,之后在需要的地方,使用引入(Include)语法,把这些片段引入进来,从而避免重复代码,这样形成了组件化的雏形,常见的动态脚本语言都有自己的模板引擎,例如 PHP、ASP 和 JSP:

    <!-- nav.jsp -->
    <nav>
      <!-- 导航 -->
    </nav>
    
    <!-- index.jsp -->
    <jsp:include page="nav.jsp" />
    

    只是这些片段在数据管理方面仍然会比较麻烦,还是需要使用客户端 JavaScript 脚本,手动控制数据和 HTML 视图的同步。而对于样式,也还是存在全局污染的问题。
    再后来,有些高级的开发语言,例如 Java, 推出了基于服务器的组件化开发技术,例如 JSF (JSP 的后继),基于 MVC 设计模式,通过 Java Class (POJO) 定义数据模型(Model),为 JSF 页面模板提供数据。JSF 的数据模型中有事件和生命周期相关的方法,而模板和数据模型通信的方式是 Ajax,通过使用 JSF facelets 组件的方式,可以直接发送 Ajax 请求,调用模型中的方法:

    <!-- index.xhtml -->
    <html
      xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:f="http://xmlns.jcp.org/jsf/core"
    >
      <h:commandButton id="submit" value="Submit">
        <f:ajax event="click" />
      </h:commandButton>
      <h:outputText id="result" value="#{userNumberBean.response}" />
    </html>
    
    // UserNumberBean.java
    @Named
    @RequestScoped
    public class UserNumberBean implements Serializable {
    	/* 其它代码省略 */
    
        public String getResponse() {
            if ((userNumber != null)
                    && (userNumber.compareTo(dukesNumberBean.getRandomInt()) == 0)) {
                return "Yay! You got it!";
            }
            if (userNumber == null) {
                return null;
            } else {
                return "Sorry, " + userNumber + " is incorrect.";
            }
        }
    }
    
    

    代码来源:Jarkarta EE 官方示例
    不过这种方式严格限定了编程语言,例如要用 JSF 技术就必须要使用 Java,并且样式污染的问题和客户端数据管理的问题仍然没有解决。
    随着 Node.js 的普及,JavaScript 可以脱离浏览器运行了,并且带来了 npm 包管理器,基于 npm 庞大的工具链,可以 Node.js 的代码打包成浏览器中能够运行的代码。而这期间,产生了像 React、Vue 和 Angular 这样的、适合大型前端项目开发的库和框架。

    在这里插入图片描述

    React 和 Vue 目前的流行程度比较高一些,它们都是纯客户端的、组件化的 JS 库,不依赖任何后端编程语言,让程序员都能够快速上手。不过,随着项目规模的扩大,如何利用好这些库进行组件化开发,成了前端工程师必须要掌握的课题。

    什么是组件

    那么到底什么是组件呢?你想一下日常生活中,电脑上的硬件,例如显卡、内存、CPU,或者汽车的零部件:轮胎、发动机、方向盘等,这些都属于组件,它们组合起来能形成一个完整可用的产品,对于遵循了设计规范的组件,只要型号匹配,无论品牌、样式,都可以互相兼容。
    我们前端工程师其实就当于是一个工厂,我们需要按照一定的规范,产生出合格的网页组件,利用它们组装成完整的页面。组件一般包含 HTML 模板、CSS 样式和 JavaScript 数据逻辑,自成一体,可以直接在其它组件中使用,组件本身的模板、样式和数据不会影响到其它组件。组件还包含一系列可配置的属性,动态的产生内容。

    常见的基础组件有按钮、导航、提示框、表单输入控件、对话框、表格、列表等,我们在它们的基础上又能组合出更复杂的组件,那么对于前端中的组件的定义就非常广泛了,小到一个按钮,大到一个页面都可以形成一个组件,例如两个相似的页面,可以复用一个页面组件,只需要通过修改组件的属性,来形成一个新的页面。

    在这里插入图片描述

    为什么要组件化开发

    你可能也知道,React 和 Vue 其实也可以完全按照传统的网页开发方式进行开发,最多是把网页大体分成几个部分,放到单独的几个文件里就好了,对于简单的网站来说没什么问题,但是如果开发的是大型的应用,例如网页版的 QQ 音乐、微信、邮箱等,它们有大量的、细小的组件,并且重复出现,这时如果针对每个页面编写 HTML 和样式,那么就会造成太多冗余代码了。

    <!-- playlist.html -->
    <div class="card">
      <div class="card__title"></div>
      <div class="card_content"></div>
    </div>
    
    <!-- homepage.html -->
    <div class="card">
      <div class="card__title"></div>
      <div class="card_content"></div>
    </div>
    
    <!-- user.html -->
    <div class="card">
      <div class="card__title"></div>
      <div class="card_content"></div>
    </div>
    

    如果使用组件化的方式,我们可以把重复出现的页面内容定义成组件,这样就不用复制粘贴同样的代码了,减少代码的体积:

    <!-- 伪组件 -->
    <!-- Card.comp -->
    <div class="card">
      <div class="card__title"></div>
      <div class="card_content"></div>
    </div>
    
    <!-- playlist.html -->
    <Card />
    
    <!-- homepage.html -->
    <Card />
    
    <!-- user.html -->
    <Card />
    

    当某个页面内容是复合组件时,那么可以直接把基础组件直接拿过来应用:

    <Card>
      <Title></Title>
      <Button></Button>
    </Card>
    

    利用这种方式,甚至可以达到 1 分钟产生一个新页面的恐怖速度,这对于你来说,节省时间去摸鱼,岂不美哉?

    <Page title="页面1" data="{...}" /> <Page title="页面2" data="{...}" />
    

    对于大型的公司来说,公司的网站、APP、桌面应用、Web 端应用等的设计风格都是一样的,同样的组件会在不同平台中使用,这个时候团队之间可以共享一套组件库,复用到各端平台上,减少重复开发的成本。React 和 Vue 都支持创建跨平台的应用,这时组件化开发就显得更重要了:

    在这里插入图片描述

    使用组件化开发之后,代码也容易维护了,如果页面某个部分出了问题,那么我们可以针对出现问题的组件进行修复,多次用到这个组件的地方也都会一起修复了。
    最后,设计师在设计产品界面的时候,会把重复出现的 UI 也做成『组件』,这个组件的概念几乎和前端中的组件一模一样,这时可以跟设计师交流想法,看看他/她是怎么规划组件的,这样也减少了在开发时,设计规划组件的时间。

    接下来分享一下我在组件化开发中总结的经验:

    一、组件的规划

    在正式进行前端应用开发之前,需要有充分的时间来分析,看看页面上的哪些内容需要做成组件。这一步只需要大致规划一下:

    • 如果公司设计师提供了详细的设计规范,那么直接按照规范中的组件来开发就可以了。

    在这里插入图片描述

    • 如果只有设计稿,那么就看看哪些内容有 2 次或更多次在其它页面中用到了,这些大概率需要设计为组件。
    • 如果连设计稿都没有,那么可以用市面上现成的组件库,例如 ant design。
    • 如果没有设计稿,还要自己从零开发,那么可以根据通用的套路,把基础组件,例如按钮、菜单等,规划出来,并把可能会多次用到的页面内容,也规划出来,例如导航,底部信息、联系方式区域,这样可以只改动需要变化的部分,不影响其它部分。

    这一步不用太过详细,浪费太多时间,后续开发的时候如果遇到不确定是否要写成组件的部分,可以直接把这部分代码写到大的组件里,如果其它组件又用到了,再把它抽离成组件。

    二、组件代码管理

    组件的代码应该遵循就近原则,也就是说:

    • 和组件有关的 HTML、CSS 、JS 代码和图片等静态资源应该放在同一个目录下,方便引用。
    • 组件里的代码应该只包括跟本组件相关的 HTML 模板、CSS 样式和 JS 数据逻辑。
    • 所有的组件应放到一个统一的『组件文件夹中』。

    如果组件之间有可以复用的 HTML 和 CSS,那么这个复用的部分可以直接定义成一个新的组件。

    如果组件之间有可以复用的 JS 数据逻辑,那么可以把公用的数据逻辑抽离出来,放到公共的业务逻辑目录下,使用到该逻辑的组件,统一从这个目录中导入。

    如果项目中使用到了全局状态管理,那么状态管理的数据应放在独立的目录里,这个目录还会存放分割好的状态片段 reducer,之后统一在 store 中合并。

    对于项目中的** API 处理**,可以把它们单独放到一个文件夹里,对于同一个数据类型的操作,可以放到同一个 js 文件里,例如对 user 用户数据的增删改查,这样能尽最大可能进行复用,之后在组件里可以直接引入相关 api 进行调用。如果直接写在组件里,那么使用相同 API 的组件就会造成代码重复。
    例如下面是一个组件化开发的目录结构示例(框架无关):

    project
    |-- components                # 所有组件
          |-- Card                # Card 组件
              |-- index.js        # Card 组件 js 代码
              |-- Card.html       # Card 组件 html 模板
              |-- Card.css        # Card 组件 css 样式
              |-- icon.svg        # Card 组件用到的 icon
    |-- logics                    # 公共业务逻辑
          |-- getUserInfo.js      # 例如获取用户信息
    |-- data                      # 全局状态
          |-- store.js            # 全局状态管理 store
          |-- user.reducer.js     # user reducer
          |-- blogPost.reducer.js # blogPost reducer
    |-- apis                      # 远程请求 API 业务逻辑
          |-- user.js             # user API
          |-- blogPost.js         # blogPost API
    

    三、组件样式管理

    在编写组件样式的时候,应只设置组件 CSS 盒子内部的样式,影响外部布局的样式要尽可能的避免,而应该由使用该组件的父组件去设置。例如,如果有一个组件设置了外边距,但是这个组件经常会用于 grid 或 flex 布局中,那么这个额外的边距会对布局造成影响,只能通过重置外边距的方式取消边距,这就不如组件不设置外边距,由父组件的布局决定它的位置,或者外边距。

    在这里插入图片描述

    类似的还有定位相关的样式,绝对定位、固定定位等对文档流有影响,应交由父组件决定,除非这个组件只有绝对定位这一种情况,例如对话框。
    组件中的 CSS 要局部化,以避免影响全局样式。传统的 CSS 样式是全局的,如果有两个不同的组件,使用了相同的 class 名字,那么后定义的样式会覆盖之前定义的。一般前端库中都有定义局部样式的功能,例如通过 CSS Modules。

    <!-- Vue -->
    <style scoped></style>
    
    <!-- React,通过文件名 -->
    Button.module.css
    

    修改子组件的样式时,优先使用选择器特异性(CSS Specificity)策略选定特定元素,而行内样式(inline-style)在设置简单样式的时候使用,尽一切可能避免 !important,因为如果再有上一层组件(爷爷组件)需要修改这个组件的样式时,就会很困难了。

    四、组件属性管理

    组件属性的命名要与它实际展示的内容相符。例如一个博客文章组件,title 属性表示标题,content 代表内容,showFullArticle 表示是否显示全文。

    <!-- 不推荐,full 表示什么? -->
    <BlogPost title="" content="" full="" />
    <!-- 推荐 -->
    <BlogPost title="" content="" showFullArticle="" />
    

    组件的属性应有必要的类型检查,避免在使用属性时出现异常,例如在需要数组的地方传递了布尔类型,那么如果代码有遍历数组的逻辑,就会出错。

    props: {
    	title: String,
      content: String,
      showFullArticle: Boolean
    }
    

    代表事件的属性,应该和现有的 HTML 事件名称规范保持一致,以 on 开头,后面用英文表示会触发的事件,例如 onEdit 表示会触发编辑事件。

    <BlogPost onEdit="" />
    

    组件的属性不能直接和状态进行捆绑,而是应该只作为状态的初始值。如果把属性值作为状态值,那么就破坏了单一数据流向机制,此时该组件可以通过自身修改状态,也能通过父组件的属性变化修改状态,很容易造成数据的不一致。推荐的做法是,设置一个初始值属性,可以通过父组件传递进来,当作状态的初始值,然后丢弃,后续只通过该组件修改状态值。

    const { initialTitle } = props;
    const title = state(initialTitle);
    
    // 修改
    updateTitle() {
     title = "...";
    }
    

    五、组件状态管理

    组件的状态分为全局状态和局部状态两种。
    局部状态是定义在组件本身的状态,应由组件本身内部管理,当子组件需要该组件的状态值时,通过属性传递给子组件,此时状态变化时,子组件也会自动刷新。

    // 父组件
    const someState = state("");
    
    <ChildComponent prop1="someState"></ChildComponent>;
    

    当子组件需要给父组件传递状态的值时,要通过事件的方式传递给父组件,尽最大可能避免使用 ref

    // 父组件
    function getStateVal(val) {
      console.log(val);
    }
    <ChildComponent onChange="getStateVal" />
    
    // 子组件
    <input onChange="e => getStateVal(e.target.value)" />
    

    状态的变化还应只通过事件或生命周期来进行,不能在其它同步执行的代码中进行,这样不会引起组件的刷新。

    const someState = state();
    
    // 错误
    const state = "newState";
    
    // 正确
    handleButtonClick() {
      someState = "newState";
    }
    

    全局状态是多个组件共享的,如果有多个组件共享某个状态,那么应该把状态定义在这些组件统一的、最接近的父组件中,或者使用全局状态管理库。

    在这里插入图片描述

    全局状态的修改,应该由类似于 actions 的行为触发,然后使用 reducer 修改状态,这样能追溯状态的变化路径,方便调试和打印日志。

    // 组件
    function updateState() {
      emitAction("changeState");
    }
    
    // reducer
    function someState(state, action) {
    	switch(action) {
        "changeState": someState => {
          	log(someState);
        		return newState
        }
      }
    }
    

    全局状态推荐按领域(Domain)来拆分 reducer,而不是按页面。例如按 user 用户、文章 posts、评论 comments 来拆分,而不是以 HomePage 主页、BlogPostListPage 博客列表页,BlogPostPage 博客详情页这样来拆分。这样做的好处是,能够最大限度的复用 reducer 中的逻辑。

    // userReducer
    
    {
    	"updateUser": ...
      "deleteUser": ...
      /* ... */
    }
    

    六、组件的组合

    前端开发就是组合不同的组件。
    在组合组件的时候,尽量使用『插槽』的形式(例如 React 的 children/render props,Vue 的 slot),这样可以减少组件的嵌套,避免多层传递属性或事件监听。
    使用 slot:

    // Layout 组件
    <div>
      <!-- nav slot -->
      <!-- content slot -->
      <!-- footer slot -->
    </div>
    
    // 首页 function handleNavChange() {}
    
    <Layout>
      <nav onChange="handleNavChange"></nav>
      <main></main>
      <footer></footer>
    </Layout>
    

    不使用 slot:

    // Layout props: { onNavChange: function }
    <Layout>
      <!-- 还需再传递一层 -->
      <nav onChange="onNavChange"></nav>
      <main></main>
      <footer></footer>
    </Layout>
    
    // 首页 function handleNavChange() {}
    <Layout onNavChange="handleNavChange" />
    

    如果有循环展示列表的地方,需要对循环中最外层的组件设置 key,这样在列表发生变化时,能帮助前端库判断是否可以通过排序的方式,重复利用现有的组件,来更新视图,而不是销毁重建。

    let todos = [{id: 1, content: "todo1"}, {id:2, content: "todo2"}, {id:3,
    content: "todo3"}];
    
    <List>
      for todo in todos:
      <item content="todo.content" key="todo.id" />
    </List>
    
    // todos 顺序变化,列表也只是根据 id 调整顺序,不会销毁重建 todos = [{id: 3,
    content: "todo3"}, {id:2, content: "todo2"}, {id:1, content: "todo1"}];
    

    如果有按条件展示组件的地方,且切换频率高,或有动画需求,要使用设置 css display 的方式,例如 vue 中的 v-show,如果切换频率低,可以使用加载、销毁的方式,例如 vue 中的 v-if,React 中使用 && 逻辑判断。

    七、组件的复用

    在复用组件的时候,可以通过改变组件的属性来修改一些简单的组件内容。

    <Card title="" content="<ContentComp />" />
    

    如果组件结构类似,但是有些内部的组件不一样,可以考虑通过『插槽』来复用。

    <!-- Comp -->
    <div>
      <h1></h1>
      <!-- slot -->
    </div>
    
    <!-- 其它组件 -->
    <Comp>
      <p>替换 slot</p>
    </Comp>
    

    如果有业务逻辑需要复用,尤其是涉及到状态变化的,那么可以把它抽离为公共的业务逻辑,利用 Hooks(React)或 Composables (Vue)来复用。

    // 公共逻辑 (/logic/useSomeLogic.js)
    function useSomeLogic() {
      const someState = state();
      const updateState = (v) => (someState = v);
      return {
        someState,
        updateState,
      };
    }
    
    // 组件1复用
    import userSomeLoginc from "/logic/useSomeLogic.js";
    const { someState, updateState } = useSomeLogic();
    
    // 组件2复用
    import userSomeLoginc from "/logic/useSomeLogic.js";
    const { someState, updateState } = useSomeLogic();
    

    如果有视图样式需要复用,那么可以直接把这部分再抽离成一个新的组件。

    小结

    这篇文章从组件的代码、样式、属性、状态、组合和复用的这几个场景上,总结了一些我在前端开发中的一些经验和个人看法,可能并不适用所有项目,如果你有更好的最佳实践和经验,欢迎分享!如果觉得本文有帮助,请分享给其它人,感谢!

    原文地址:https://zxuqian.cn/7-ways-to-organize-frontend-components,欢迎访问查看更多前端开发教程!
    Bilibili:峰华前端工程师
    公众号:峰华前端工程师

    展开全文
  • VUE3组件开发——下拉菜单(DropDown)

    千次阅读 2022-01-14 13:01:18
    个组件主要是实现下拉多级列表的形式 1. 环境 主要用到的环境是VScode+TS+VUE3+Bootstrap 2. 代码 这里主要就是判断是不是点击打开了下拉菜单的部分,让它显示多级列表 2.1 组件 DropDown.vue <template> &...

    VUE3组件开发——下拉菜单(DropDown)

    这个组件主要是实现下拉多级列表的形式

    1. 环境

    主要用到的环境是VScode+TS+VUE3+Bootstrap

    2. 代码

    这里主要就是判断是不是点击打开了下拉菜单的部分,让它显示多级列表

    2.1 组件

    DropDown.vue

    <template>
    <!-- 写了样式也不骑作用 -->
    <div class="dropdown" style="{display: inline-table}">
        <a href="#" class="btn btn-outline-light my-2 dropdown-toggle"  :style="{color :'black', fontSize: '18px'}">{{title}}</a>
        <!-- <ul class="dropdown_menu" :style="{display: 'block'}" v-if="isOpen"> -->
        <ul class="dropdown_menu" :style="{display: 'block'}">
        <li class="dropdown-item">
            <a href="#"  :style="{color :'black', fontSize: '18px'}">新建文章</a>
        </li>
            <li class="dropdown-item">
            <a href="#"  :style="{color :'black', fontSize: '18px'}">编辑资料</a>
        </li>
        </ul>
    </div>
    </template>
    <script lang='ts'>
    import { defineComponent, ref } from 'vue'
    
    export default defineComponent({
      name: 'Dropdown',
      props: {
        title: {
          type: String,
          required: true
        }
      },
    
      setup () {
        const isOpen = ref(false)
        const toggleOpen = () => {
          isOpen.value = !isOpen.value
        }
        return {
          isOpen,
          toggleOpen
        }
      }
    })
    </script>
    
    

    为了让其不点击就显示出来我就直接,使用display:block

    将行内样式的ul元素变为块级的。去显示判断,这样就不需要点击就可以显示。做效果预览。

     *<!-- <ul class="dropdown_menu" :style="{display: 'block'}" v-if="isOpen"> -->*
    
      <ul *class*="dropdown_menu" :*style*="{display: 'block'}">
    

    2.2 引用组件

    在GlobalHeader里面直接进行引用,变成GlobalHeader的子组件。

     <dropdown :*title*="`你好 ${user.name}`"></dropdown>
    

    放到GlobalHeader组件定义里面。

    关于父子组件的传值已经方法·定义,可以看看Vue专栏里面的相关内容。

    导入组件:ts

    import* Dropdown *from* './DropDown.vue'
    
    
    

    组件定义:

    export default defineComponent({
        //组件名称
        name:'Home',
        //接收父组件的数据
        props:{
             
        },
    

    完整代码:

    //创建一个globalheader组件
    <template>
        <nav class="navbar navbar-dark bg-primary justify-content-between mb-4 px-4">
        <a class="navbar-borand" href="#" :style="{color :'black', fontSize: '18px'}">者也专栏</a>
        <ul v-if="!user.isLogin" class="list-inline mb-0">
            <li class="list-inline-item"><a href="#" class="btn-outline-light my-2 " :style="{color :'black', fontSize: '18px'}">注册</a></li>
            <li class="list-inline-item"><a href="#" class="btn-outline-light my-2" :style="{color :'black', fontSize: '18px'}">登录</a></li>
        </ul>
        <ul v-else class="list-inline mb-0">
            <li class="list-inline-item">
              <dropdown :title="`你好 ${user.name}`"></dropdown>
              <!-- <a href="#" class="btn btn-outline-light my-2" :style="{color :'black', fontSize: '18px'}">你好{{user.name}}</a> -->
              </li>
        </ul>
        </nav>
    </template>
    <script lang="ts">
    import { defineComponent, PropType } from 'vue'
    import Dropdown from './DropDown.vue'
    export interface UserProps {
        isLogin:boolean;
        name?:string;
        id?:number;
    }
    export default defineComponent({
      name: 'GlobalHeader',
      components: {
        Dropdown
      },
      props: {
        user: {
          type: Object as PropType<UserProps>,
          required: true
    
        }
      }
    
    })
    </script>
    
    

    3. 运行

    image-20220114130024955

    展开全文
  • 手把手教你实现vue下拉菜单组件

    千次阅读 2021-01-13 04:07:07
    这篇文章我们一起来实现一vue的下拉菜单组件。像这种基本UI组件,网上已经有很多了,为什么要自己实现呢?其实并不是有意重复造轮子,而是想通过这过程回顾一下vue组件开发的一些细节和注意事项。为什么选择下拉...
  • 目录基础思考动手自定义页面结构渲染页面样式绑定事件转为组件创建组件所需的目录及页面复制组件内容声明组件js转换使用引入组件使用组件 基础 参考: 小程序开发文档-自定义组件 小程序开发文档-Component 构造器 ...
  • 【Java Swing开发 组件与布局】

    千次阅读 多人点赞 2021-04-19 22:27:03
    组件及事件处理1 Java Swing概述2 窗口2.1 JFrame常用方法3 常用组件与布局二级目录级目录4 处理事件二级目录级目录 1 Java Swing概述 Java通过图形用户界面(GUI: Graphics User Interface) ,用户和程序之间...
  • meta: { isShowFooter: true }, }, //配置默认重定向 { path: "*", redirect: "/home", }, ] 此时你已经可以在地址栏中手动输入查看静态组件啦 无法跳转的情况:更改router后需要重启npm服务,重启下就好了 ...
  • 今天给大家带来React项目结合Antd的时候如何渲染二级菜单 ...其中有一isSiderbar标记,这就是我们待会用来判断是否是sidebar的类型。 3.接下来我们写二级菜单的数据 其中有isresourceManagem...
  • 一、前言 首先,介绍一UGUI,NGUI是UGUI的前身,Unity开发团队将NGUI的开发团队收到自己开发团队下,并且...二、Dropdown 下拉菜单组件介绍 Dropdown 下拉菜单,可快速创建大量选择项,无需开发者自己写脚本实现。
  • 创建窗口程序(JFrame),标题栏起名为“浏览器”,有一个菜单条,有“文件”、“编辑”、“查看”3个菜单。文件菜单有两个菜单项,一项是“打开”,一项是“保存”,“打开”项做成子菜单,有两个菜单项“打开x...
  • JavaGui界面菜单组件

    千次阅读 2021-02-02 15:17:31
    在实际开发中,除了主界面,还有一类比较重要的内容就是菜单相关组件,可以通过菜单相关组件很方便的使用特定的功能,在AWT中,菜单相关组件的使用和之前学习的组件是一模一样的,只需要菜单条、菜单菜单项组合...
  • 在项目根目录(本项目根目录为 my_csdn,该目录下存在一同名的 my_csdn 文件)创建 navbar 应用,同步需要注册在 settings.py 中。 还有为了后续实现组件化开发,还需要调整一下项目结构,具体步骤如下。 ...
  • 若依管理系统(前后端分离版)-----创建三菜单 ** 使用若依系统也是图方便,但是使用的越久就会越来越依赖,因为当你再次想自己动手去写的时候就会发现,许多东西你已经忘记了 废话不多说开始本次的主要内容 ...
  • vue-ts-files是一vscode下的快速建立vue typescript组件的一款插件,通过vue-ts-files你能通过右击文件目录,创建你想要的组件。免去创建文件后不必要的snippets
  • 微信小程序自定义组件的...先创建项目需要的自定义组件文件夹(tabbar,名称自定义,以我这边为例);创建好后,右击tabbar, 选择“新建Component“,输入文件名后,小程序会自动生成js、json、wxml、wxss四文件 ...
  • Unity编辑器扩展教程 本文提供全流程,中文翻译。Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 ——... Create MenuItem —— 创建菜单项 1- - Create Level 1 Menu —— 创建一级菜单 2- - Cre...
  • 写在最前面:Jay 是我花了五天左右时间开发的同名游戏,基础机制借鉴了涂鸦跳跃,具体的参考视频...这篇日志将记录游戏中如何创建简易的主菜单。 1)首先新建一场景,命名为 Menu 。在该场景中创建新的 ...
  • Unity3D UGUI下拉菜单/Dropdown每次点击都可用 Unity3D中UGUI实现下拉菜单 Chinar-本文提供全流程,中文翻译。...即可完成一下拉菜单创建 扩展 Dropdown 组件,开启被选择按钮,再次被点击仍然可
  • Vue.js递归组件实现动态树形菜单

    千次阅读 2018-06-13 15:22:00
    只有两感觉,官网的案例太简洁,没有什么注释,看起来不太好理解,大神们的作品又比较复杂,对于初学者来说理解起来还是有难度,自己捣鼓了几天,勉强理解了递归组件菜单的实现,这里结合官网的案例,把代码和注释附上. ...
  • Menu详解():使用上下文菜单

    千次阅读 2014-08-21 17:36:12
    因为最近学的东西比较多,感想也比较多,单一的写一方面比较乏味,所以我就穿插着写了,下面我会把相关的链接给大家,供大家系统的学习。 不积跬步无以至千里,不积小流无以成江河。 (千里之行,始于足下,...
  • 在GUI程序中,创建下拉式菜单需要使用三个组件:JMenuBar(菜单栏)、JMenu(单)JMenuItem(菜单项),以记事本为例,这三个组件菜单中对应的位置如图所示。 三个关键组件的介绍 1)JMenuBar:JMenuBar表示一个水平的...
  • 菜单组件JMenuBar、JMenu、JMenuItem略解

    千次阅读 2018-12-03 16:38:12
    菜单组件JMenuBar、JMenu、...JMenuBar负责创建菜单条,即JMenuBar的一实例就是一菜单条。 JMenuBar bar = new JMenuBar(); //创建菜单条 将菜单条添加到窗口中的方法: public void setJMenuBar(JMenuBa...
  • 使用IconFont IconFont官网,进入后我们登陆,然后创建项目管理 图中的连接是Icon的地址,需要把它放...这时我们就需要使用到ant提供的Icon组件 createFromIconfontCN import { createFromIconfontCN } from '@ant
  • ANSYS 有限元分析 选择与组件

    千次阅读 2020-05-24 14:27:12
    ANSYS 有限元分析 选择与组件 ANSYS 有限元分析 修改与编辑 ANSYS 有限元分析 接触问题 ANSYS 有限元分析 加载与求解 ANSYS 有限元分析 后处理 因个人能力有限,本文难免有所疏漏/错误,不妥之处还请...
  • Tkinter 组件详解(十):Menu

    万次阅读 多人点赞 2018-12-27 10:37:59
    Menu(菜单组件用于实现顶级菜单、下拉菜单和弹出菜单。...创建顶级菜单,你需要创建个菜单实例,然后使用 add() 方法将命令和其它子菜单添加进去: import tkinter as tk root = tk.T...
  • iOS经常用到的开源库和第组件

    千次阅读 2016-12-12 21:09:11
    1、通过CocoaPods安装 项目名称 ...网络请求组件 ...多缩略图缓存组件 UICKeyChainStore 存放用户账号密码组件 Reachability 监测网络状态 DateTools 友好化时间 MBP
  • TextArea右键菜单 组件使用案例

    千次阅读 2020-03-22 15:27:59
    文章目录一:下拉式菜单创建步骤:二:弹出式菜单创建步骤::选项卡窗体: 菜单是GUI中最常用的组件,菜单不是Component类的子类,不能放置在普通容器中,不受布局管理器的约束,只能放置在菜单栏中. 菜单组件菜单栏 ...
  • C#程序设计及宿舍管理系统实战 ... MDI应用程序介绍 在VC#中,MDI应用程序由两部分组成,即MDI父窗体和MDI子窗体。...一MDI应用程序可以包含一或多MDI父窗体,每MDI父窗体又可以包...
  • 组件技术介绍

    千次阅读 2018-12-03 11:16:53
    组件(component)技术是各种软件重用方法中最重要的一种方法,也是分布式计算和Web服务的基础。网络应用中的软件组件,又被称为中间件(middleware)。 组件技术的应用现在已经十分广泛,从Windows编程中使用的各种...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 96,136
精华内容 38,454
关键字:

创建菜单需要三个组件