本文将会从 NutUI 初学者的使用入手,对 NutUI 做了一个快速的概述,希望能帮助新人在项目中快速上手。

文章包括以下主要内容

  • 安装引入 NutUI
  • NutUI 组件的使用
  • NutUI 主题和样式定制
  • 国际化项目中使用 NutUI

为什么是她

Vue 给大家带来了组件化,这个功能给开发人员带来了强大并且简洁的复用组件能力。设计精美,扩展良好的组件无疑会让产品效果更加统一,带来更好的观看感觉,减少大量重复性工作,提高代码的可维护性。

当我们最初开始使用一个组件库的时候,不仅需要从组件库中简单地寻找一个能用的组件,而是从产品的角度出发,除了组件库所提供的基本组件外,寻求她所具备的其他特殊功能。

  • 安装 & 引入:支持 NPM 方式和 CDN 方式,并支持按需引入
  • 丰富的 feature:丰富的组件,自定义主题,国际化
  • 文档 & demo:提供友好的文档和 demo,支持多语言
  • 工程化:开发,测试,构建,部署,持续集成

当然了,最后这个组件库还应该有持续的更新和维护。我们找了很多组件进行分析测评。先来看一下这一期关于 NutUI 的上手结果。

什么是 NutUI

NutUI 是一款非常优秀的移动端组件库。50+组件覆盖,包含基础类、数据录入类、操作反馈类、数据展示类、导航类、布局类和业务类组件。而且组件风格统一,开发人员的持续维护,保证了组件的健壮性和可维护性,满足多数场景M端需求。同时优秀的文档和活跃的社区支持,给使用者带来最优的体验。

NutUI 从2017年开始发版,所有组件均是从京东的业务中抽离出来,然后不断整合修复,最终发展成型。专业的标准设计稿保证一致性,优秀的组件自动化测试和不断的更新保证组件的稳定性。能够解决目前市面上多数基于 Vue 开发的 M 端需求,加快使用者开发进度。那么下面我们就带大家走进 NutUI。

开始上手

我们依据 NutUI 2.2.2 版本的源码来分析该组件库的使用和注意事项。当然,NutUI 早期一定不是这样子的,我们分析的这个版本已经是经过它多次迭代优化后的,如果你想去了解它的发展历程,可以去 https://github.com/jdf2e/nutui/releases 搜索它的历史版本。同时,NutUI 也在进行 3.0 版本的开发。 3.0 版本中将会独立出 Nut-CLI,同时支持 Vue3.0 的语法,全新的组件和规范。期待你的加入。(想要成为 NutUI 的维护者吗?欢迎去 https://github.com/jdf2e/nutui/issues 中 issue 留言和加入)

安装引入

  1. 目前主流的库都支持 CDN 引入和 NPM 安装。NutUI 不例外,还更有亮点。

CDN 引入

先说一下 CDN 引入。我们只要在我们的 HTML 页面上加入如下代码,就可以完整的使用 NutUI 了。

  1. <!-- 生产环境版本,优化了尺寸和速度 -->
  2. <!-- 引入样式 -->
  3. <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@nutui/nutui/dist/nutui.min.css">
  4. <!-- 引入Vue -->
  5. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
  6. <!-- 引入组件库 -->
  7. <script src="https://cdn.jsdelivr.net/npm/@nutui/nutui/dist/nutui.min.js"></script>

当然,NutUI 在这方面比较优秀的就是可以 CDN 按需加载引入。 (下面实例为只引入 Button 组件)

  1. <body>
  2. <div id="app"><nut-button>CDN按需加载</nut-button></div>
  3. <!-- 开发环境版本,包含了有帮助的命令行警告 -->
  4. <!-- 引入样式 -->
  5. <link rel="stylesheet"href="https://cdn.jsdelivr.net/npm/@nutui/nutui/dist/packages/button/button.css"/>
  6. <!-- 引入Vue -->
  7. <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  8. <!-- 引入组件库 -->
  9. <script src="https://cdn.jsdelivr.net/npm/@nutui/nutui/dist/packages/button/button.js"></script>
  10. <script>
  11. Vue.component(button.default.name, button.default);
  12. new Vue({
  13. el: "#app"
  14. });
  15. </script>
  16. </body>

注意,CDN 引入使用组件的时候。由于 HTML 中的 attribute 名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。这意味着当你使用 DOM 中的模板时,组件中的 prop 属性 camelCase (驼峰命名法) 需要使用其等价的 kebab-case (短横线分隔命名) 命名。详情参考 Prop用法 ①

NPM 引入

NPM 引入的方式也非常简洁。我们使用 Vue-CLI 或者 Gaea CLI ② 搭建项目之后。在入口文件添加如下代码。

Gaea CLI 也是一款 Vue 技术栈单页面构建工具。且支持一键上传,TypeScript ,Skeleton等特色功能

  1. import Vue from 'vue';
  2. import Nutui from '@nutui/nutui';
  3. import '@nutui/nutui/dist/nutui.css';
  4. Nutui.install(Vue);

当然,如上引入的好处是方便,只需要三行代码就可以完整地使用 NutUI 所有的组件,但缺点也很明显,引入的组件包体积很大,通常一个项目也用不到所有的组件,会有资源浪费。

所以最佳方案推荐按需引入。在需要使用某组件的页面添加如下代码:(以下为 dialog , picker 组件按需加载)

  1. import Vue from 'vue';
  2. import { Dialog,Picker } from '@nutui/nutui';
  3. Dialog.install(Vue);
  4. Picker.install(Vue);

在这里说明一下,NutUI 会主动打包对应组件的 css 代码,而不像其他组件库直接打包所有css。

当我们这样使用的时候,觉得理所应当,那么为什么 import { Dialog } from '@nutui/nutui'; 可以实现按需引入呢?

实际上我们查看源码可以得到,NutUI 借助 webpack 的 @nutui/babel-plugin-seperate-import 组件实现将

  1. import { Dialog } from '@nutui/nutui';

转换成如下代码

  1. import Dialog from '@nutui/nutui/dist/packages/button/button.js'; // 加载构建后的JS
  2. import '@nutui/nutui/dist/packages/button/dialog.css'; //加载构建后的CSS

同时,NutUI 在构建的时候,已经构建出一个完整版的组件库包和每个组件独立的包。然后我们手动使用 Dialog.install(Vue) 进行注册。这样我们就精准地引入了对应 lib 下的 Dialog 组件的 JS 和 CSS 代码了。实现了我们的目标:按需加载。

webpack的中如何构建多个bundle呢?主要是entry选项的配置,entry的值通常是一个字符串,其实它还可以是一个对象。我们新增一个webpack配置文件,基于组件库的组件配置文件生成一个对象,key是组件名,value是组件的入口js文件,将此对象作为该配置文件的entry选项值即可,其他配置与完整版的组件库webpack配置文件一致(输出目录可根据需要自行配置)。构建时执行这两个配置文件,即可构建出一个完整版的组件库包和每个组件独立的包

  1. const cptConf = require('../src/config.json');
  2. const entry = {};
  3. //遍历所有组件
  4. cptConf.packages.map((item)=>{
  5. entry[cptName] = `./src/packages/${item.name.toLowerCase()}/index.js`;
  6. });
  7. module.exports = {
  8. entry
  9. };

组件开箱即用

上面我们已经完整的引入了 NutUI,接下来,我们将使用案例来看一下如何使用组件。

使用前准备

我们在使用一个组件库的时候,最好在 NutUI 官网上提前把该库所有的组件全部通读一遍。这样,不仅使我们对组件库有一个完整的印象,而且更有利于我们在使用组件的时候具有更多选择性。比如以下一个案例:

一个 app 开发中,进入项目后,常常会出现一个协议的提示,如图:

大家是不是一下子就想到了使用 Dialog 组件,但是在使用过程中,发现内容过长,而且基础的 Dialog 不支持内容自定义,更不支持内容的滚动。这个时候是不是束手无策?其实,换种方式,使用 Popup 组件,然后居中展示,内容全部支持自定义,不就完美的解决了我们的需求。所以建议大家在使用前通读一下所有组件,磨刀不误砍柴工,反而更加有效的提高开发效率。

渐入佳境

组件了解结束之后,正式进入开发,激动人心的时候终于到了。我们先来看几个常规的组件。

日历组件:日历组件开发过程中常见的刚需组件,一个优秀的日历组件需要包含能够选择日期,区间选择等功能。

NutUI 的日历组件的日历区间选择功能,支持同一天的选择。比如选择2020/05/20-2020/05/20,这可是其他组件不支持的功能哦!

我们使用按需引入的方法来使用日历组件,在 main.js 中加载日历组件

  1. import { Calendar } from '@nutui/nutui';
  2. Calendar.install(Vue);

接下来我们在需要的页面中添加指定组件

  1. <nut-calendar
  2. :is-visible.sync="isVisible2"
  3. :default-value="data2"
  4. :is-auto-back-fill="true"
  5. @close="switchPickerClose('isVisible2')"
  6. @choose="setChooseValue2"
  7. >
  8. </nut-calendar>
  9. <nut-cell :showIcon="true" :isLink="true" @click.native="switchPicker('isVisible2')">
  10. <span slot="title"><label>日期选择</label></span>
  11. <span slot="sub-title">有默认日期,选择后自动回填的~~~</span>
  12. <div slot="desc" class="selected-option" >
  13. <span class="show-value">{{date2 ? date2 : '请选择日期'}}</span>
  14. </div>
  15. </nut-cell>
  16. // js部分
  17. export default {
  18. data() {
  19. return {
  20. isVisible2: false,
  21. date2: '2020-12-22',
  22. };
  23. },
  24. methods: {
  25. setChooseValue2(param) {
  26. this.date2 = param[3];
  27. },
  28. switchPickerClose(isVisible2){
  29. this.isVisible2=!this.isVisible2;
  30. }
  31. }
  32. };

上面代码中,is-visible.sync 是来控制日历是否展示,default-value 是展示日历的默认日期,close 是关闭事件,choose是我们选择日期的事件触发。默认日历组件时不显示的,我们需要通过点击 Cell 来控制日历组件,这样一个完整的日历效果就实现了,剩下的就是我们处理自己的业务了!

思考 : 为什么要使用 .sync ?

除了日历组件这种需要在页面上放置组件来展示的,部分组件支持直接函数式调用,比如 Dialog组件,我们来体验一下。

先全局注册 Dialog 组件。

  1. import { Button , Dialog } from '@nutui/nutui';
  2. Button.install(Vue);
  3. Dialog.install(Vue);

然后我们在按钮上添加一个事件,在事件中使用dialog

  1. <nut-button
  2. @click="clickHandler"
  3. >
  4. 提交
  5. </nut-button>
  6. //js部分
  7. export default {
  8. data() {},
  9. methods: {
  10. clickHandler() {
  11. this.$dialog({
  12. title: "提交",
  13. content: "你确定提交当前数据吗",
  14. closeBtn:true, //显式右上角关闭按钮
  15. onOkBtn(event) { //确定按钮点击事件
  16. alert("okBtn");
  17. this.close(); //关闭对话框
  18. },
  19. onCancelBtn(event) { //取消按钮点击事件,默认行为关闭对话框
  20. alert("cancelBtn");
  21. //return false; //阻止默认“关闭对话框”的行为
  22. },
  23. onCloseBtn(event) { //右上角关闭按钮点击事件
  24. alert("closeBtn");
  25. //return false; //阻止默认“关闭对话框”的行为
  26. },
  27. closeCallback(target) {
  28. alert("had close"); //对话框关闭回调函数,无论通过何种方式关闭都会触发
  29. }
  30. });
  31. }
  32. }
  33. };

dialog 的内容不仅支持文字,同时支持图片类型。

  1. this.$dialog({
  2. type:"image", //设置弹窗类型为”图片弹窗“
  3. link:"http://m.jd.com", //点击图片跳转的Url
  4. imgSrc:"m.360buyimg.com//5b9549eeE4997a18c/070eaf5bddf26be8.jpg", //图片Url
  5. onClickImageLink:function(){
  6. //图片点击事件,默认行为是跳转Url
  7. console.log(this);
  8. //返回false可阻止默认的链接跳转行为
  9. }
  10. });

为什么我们使用 Dialog 可以直接通过 this 来直接调用呢?原因就是 Dialog 组件在构建的时候,其实构建了两种:一种支持我们使用组件式使用,另一种支持我们使用函数式调用。

  1. import DialogVue from './dialog.vue';
  2. import Dialog from './_dialog';
  3. import './dialog.scss';
  4. const DialogArr = [Dialog, DialogVue];
  5. DialogArr.install = function(Vue){
  6. Vue.prototype['$dialog'] = Dialog;
  7. Vue.component(DialogVue.name, DialogVue);
  8. }

上面代码我们可以看到,Dialog 构建时,不仅使用了 Vue.prototype 来扩展一个新的方法,同时也使用了 Vue.component 来实现组件式调用。

额外惊喜

NutUI 中目前不仅有传统的通用组件,现在也在逐渐增加好多特色组件。比如目前已经有的抽奖组件和签名组件。先去官网一睹为快吧!

(更多组件和使用方法参考官网文档 https://nutui.jd.com/)

主题定制

使用任何一个组件功能可以类似,但样式却是各式各样。如何在使用 NutUI 的基础上实现自己的样式定制呢?

全局定制

首先我们来看,NutUI 中所有公共的样式都在 dist\styles\variable.scss 中。当我们想要修改的时候,可以在项目中创建一个 scss 文件,然后复制公共样式中所有变量。

我们需要修改一下配置。在vue.config.js 的 css 配置或者 webpack 中的 sass-loader 的配置。引入我们自定义的 scss 文件,注意属性哦。

  1. module.exports = {
  2. css: {
  3. loaderOptions: {
  4. // 给 sass-loader 传递选项
  5. scss: {
  6. // @/ 是 src/ 的别名
  7. // 注意:在 sass-loader v7 中,这个选项名是 "data"
  8. prependData: `
  9. @import "@/assets/custom_theme.scss"; //这个是我们自定义的scss文件@import "@nutui/nutui/dist/styles/index.scss";
  10. `,
  11. }
  12. },
  13. }
  14. }

然后我们使用组件的时候,需要引入 SCSS 文件,而不是 CSS 文件。这样变完成了对 NutUI 的全局样式定制。

  1. import Nutui from '@nutui/nutui';
  2. import '@nutui/nutui/dist/nutui.scss';

私人定制

当然,如果我们项目中某个特殊组件需要修改样式,而且不想影响该组件在其他地方的使用,我们可以在页面上直接使用 /deep/ 进行样式修改,但是注意添加对样式style 添加 scoped 哦!

/deep/ 是Vue提供的深度选择器。详情参考 VUE官网 Scope CSS ③

国际化

随着越来越多的多语言项目进入我们的开发需求中。国际化方案成为一种必需品。谈到 Vue 的国际化方案,大家很容易会联想到 vue-i18n 方案,NutUI 并未引入 vue-i18n,不过它是可以很好地兼容 vue-i18n 。

NutUI 的国际化

所有的国际化方案都会用到语言包,语言包通常会返回一个 JSON 格式的数据,NutUI 组件库的语言包在 locale/lang 目录下。我们使用的时候,需要在引入 NutUI 的时候同时引入对应的语言包。如下是引用了英语语言包。

  1. import Vue from 'vue';
  2. import NutUI from '@nutui/nutui';
  3. import enUS from '@nutui/nutui/dist/locales/lang/en-US';
  4. Vue.use(NutUI , {
  5. locale: 'en-US',
  6. lang: enUS
  7. });

这样我们的页面中所有关于 NutUI 组件的都会使用英语语言展示,如图:

整个项目的国际化

当然,这只是修改了组件内部的语言,如何将 NutUI 和自己的语言包完美融合呢?我们构建一个自己的语言包。

  1. // zh_cn.js文件
  2. export default {
  3. app: {
  4. hello: '你好,世界!'
  5. }
  6. }
  7. // en_us.js文件
  8. export default {
  9. app: {
  10. hello: 'Hello,World!'
  11. }
  12. }

然后再入口文件中进行引入。

  1. import Vue from 'vue';
  2. import VueI18n from 'vue-i18n';
  3. import {locale} from '@nutui/nutui';
  4. import enUS from '@nutui/nutui/dist/locales/lang/en-US';
  5. import zhCN from '@nutui/nutui/dist/locales/lang/zn-CH';
  6. import enLocale from './en_us';
  7. import zhLocale from './zh_cn';
  8. Vue.use(VueI18n);
  9. Vue.locale = () => {};
  10. // 将语言包进行合并
  11. const messages = {
  12. en: {
  13. ...enUS,
  14. ...enLocale
  15. },
  16. zh: {
  17. ...zhCN,
  18. ...zhLocale
  19. }
  20. }
  21. const i18n = new VueI18n({
  22. locale: 'zh', // 设置默认语言
  23. messages: messages // 设置资源文件对象
  24. })
  25. //
  26. const app = new Vue({
  27. el: '#app',
  28. i18n
  29. })

这样便将 i18n 和我们 NutUI 的语言包进行了合并。如何在页面中使用呢?

  1. <template>
  2. <nut-navbar :title="$t('app.hello')" @click-left="show=true">
  3. </nut-navbar>
  4. </template>

我们在 JS 中使用的时候需要加上 this。例如:

  1. created () {
  2. console.log('start to enter created ', this.$t('app.hello'))
  3. }

接下来,我们在语言切换的按钮上绑定如下事件,即可完美的实现语言切换功能了。

  1. tabEn: function () {
  2. this.$i18n.locale = 'en'
  3. },
  4. tabCn: function () {
  5. this.$i18n.locale = 'zh'
  6. }

这样,我们就完美的实现了多语言的展示和切换功能。是不是很优秀?

文档 & Demo

当我们使用一个组件库的时候,友好的文档和 Demo 是必不可少的。她可以让我们更方便快捷的使用。NutUI 的 Demo 和文档是分开的。从 NutUI 的Github ④中可以看出,NutUI 把所有的组件都放在 src/packages 下面。每一个组件大概由下面几部分组成。

其中_test 文件夹内是组件的单元测试。NutUI 如何进行单元测试可参考文章 NutUI单元测试实践 ⑤。其中详细介绍了如何编写单元测试和在 NutUI 中单元测试实践。

剩下的文件中以组件命名的 js ,vue , css 文件,是该组件的核心。上面也介绍了一个组件是如何从0开始构建的,一个通用的组件从参数传入,参数处理,校验,参数存储,function 回调等各种特性保证才产出。

demo.vue 文件包含了该组件各种常规用法。我们官网上所有的实例写法,都可以在对应组件的 demo 文件种找到。同学们可以如果有需求,可以只看 demo ,来 copy 你想要的功能哦!

最后我们说到的是.md 文件。md 文件就是我们官网上对该组件的说明和使用方法,我们是如何将 md 直接变成我们的官网呢,NutUI官网构建的关键技术揭秘 ⑥可以得到答案哦!

结束语

至此,关于NutUI 的基本使用,我们今天就先介绍到这里。是不是很心动,赶快在你的项目中使用起来吧!同时 https://github.com/jdf2e/nutui/issues 欢迎你的建议。本文中所有的示例都收录在https://github.com/jdf2e/nutui-demo 欢迎访问点赞!!

参考连接

  1. Vue关于prop用法 https://cn.vuejs.org/v2/guide/components-props.html
  2. Gaea CLI https://github.com/jdf2e/Gaea4
  3. VUE官网 Scope CSS https://vue-loader.vuejs.org/zh/guide/scoped-css.html#混用本地和全局样式
  4. NutUI Github地址 https://github.com/jdf2e/nutui
  5. NutUI单元测试实践 https://juejin.im/post/5e66ee55f265da57133b3927
  6. NutUI官网构建的关键技术揭秘 https://juejin.im/post/5ebb4a686fb9a0437055c33d

十分钟快速上手NutUI的更多相关文章

  1. [转帖]十分钟快速理解DPI和PPI,不再傻傻分不清!

    十分钟快速理解DPI和PPI,不再傻傻分不清! https://baijiahao.baidu.com/s?id=1605834796518990333&wfr=spider&for= ...

  2. 三分钟快速上手TensorFlow 2.0 (下)——模型的部署 、大规模训练、加速

    前文:三分钟快速上手TensorFlow 2.0 (中)——常用模块和模型的部署 TensorFlow 模型导出 使用 SavedModel 完整导出模型 不仅包含参数的权值,还包含计算的流程(即计算 ...

  3. 三分钟快速上手TensorFlow 2.0 (中)——常用模块和模型的部署

    本文学习笔记参照来源:https://tf.wiki/zh/basic/basic.html 前文:三分钟快速上手TensorFlow 2.0 (上)——前置基础.模型建立与可视化 tf.train. ...

  4. 三分钟快速上手TensorFlow 2.0 (上)——前置基础、模型建立与可视化

    本文学习笔记参照来源:https://tf.wiki/zh/basic/basic.html 学习笔记类似提纲,具体细节参照上文链接 一些前置的基础 随机数 tf.random uniform(sha ...

  5. 【Microsoft Azure 的1024种玩法】一.一分钟快速上手搭建宝塔管理面板

    简介 宝塔Linux面板是提升运维效率的服务器管理软件,其支持一键LAMP/LNMP/集群/监控/网站/FTP/数据库/JAVA等100多项服务器管理功能.今天带大家一起学习的内容为一分钟快速上手搭建 ...

  6. HDFS+MapReduce+Hive+HBase十分钟快速入门

    1.     前言 本文的目的是让一个从未接触Hadoop的人,在很短的时间内快速上手,掌握编译.安装和简单的使用. 2.     Hadoop家族 截止2009-8-19日,整个Hadoop家族由以 ...

  7. 【PyTorch v1.1.0文档研习】60分钟快速上手

    阅读文档:使用 PyTorch 进行深度学习:60分钟快速入门. 本教程的目标是: 总体上理解 PyTorch 的张量库和神经网络 训练一个小的神经网络来进行图像分类 PyTorch 是个啥? 这是基 ...

  8. 十分钟快速入门 Python,看完即会,不用收藏!

    本文以 Eric Matthes 的<Python编程:从入门到实践>为基础,以有一定其他语言经验的程序员视角,对书中内容提炼总结,化繁为简,将这本书的精髓融合成一篇10分钟能读完的文章. ...

  9. Redis数据类型简介(十分钟快速学习Redis)

    如何在ubuntu18.04上安装和保护redis 如何连接到Redis数据库 如何管理Redis数据库和Keys 如何在Redis中管理副本和客户端 如何在Redis中管理字符串 如何在Redis中 ...

随机推荐

  1. java 工具类Integer

    Integer 是lang包下的工具类 为了更加熟悉Integer中的方法使用和理解 进行了一部分代码和原代码的总结 Intrger工具类方法: * * int parseInt(String s) ...

  2. Docker学习笔记-Dockerfile文件详解

    什么是Dockerfile? Docker中有个非常重要的概念叫做--镜像(Image).Docker 镜像是一个特殊的文件系统,除了提供容器运行时所需的程序.库.资源.配置等文件外,还包含了一些为运 ...

  3. Clayff力场(转载)

    本文转载自:http://blog.sina.com.cn/s/blog_b48a7ac30102w4km.html 注意:lammps中并没有完整的clayff势函数,需要将一下三者结合使用. an ...

  4. log4j升级到log4j2

    log4j升级到log4j2 1.导入依赖 log4j2应尽量使用同一版本,否则可能出现不兼容的情况 <!-- log4j2 start --> <!-- log4j-1.2-api ...

  5. 2020,最新APP重构:网络请求框架

    在现在的app,网络请求是一个很重要的部分,app中很多部分都有或多或少的网络请求,所以在一个项目重构时,我会选择网络请求框架作为我重构的起点.在这篇文章中我所提出的架构,并不是所谓的 最好 的网络请 ...

  6. React技术实践(1)

    随着系统越来越庞大,前端也变得越来越复杂,因此,构建一套组件化的前端变得很重要了. 之前一直在使用Asp.net来进行前端的组件化,Asp.net组件化有个很大的缺陷,就是和后台代码绑定太紧密了,不符 ...

  7. HMM隐马尔可夫模型来龙去脉(二)

    目录 前言 预备知识 一.估计问题 1.问题推导 2.前向算法/后向算法 二.序列问题 1.问题推导 2.维特比算法 三.参数估计问题 1.问题推导 2.期望最大化算法(前向后向算法) 总结 前言 H ...

  8. 开源流数据公司 StreamNative 推出 Pulsar 云服务,推进企业“流优先”进程

    Apache 顶级项目 Pulsar 背后的开源流数据公司 StreamNative 宣布,推出基于 Apache Pulsar 的云端服务产品--StreamNative Cloud.该产品的发布, ...

  9. 【转】Android截屏

     http://blog.csdn.net/xww810319/article/details/17607749 Android截屏浅析 链接:http://blog.sina.com.cn/s/bl ...

  10. Java中的IO操作和缓冲区

    目录 Java中的IO操作和缓冲区 一.简述 二.IO流的介绍 什么是流 输入输出流的作用范围 三.Java中的字节流和字符流 字节流 字符流 二者的联系 1.InputStreamReader 2. ...