Activity singleInstance/singleTop启动模式的理解

Android有四种启动模式,分别是standard,singleTop,singleTask,singleInstance。下面分别简单的介绍下这四种启动模式的作用。

standard

Android 默认的一种启动模式。不需要为activity设置launchMode。这种启动模式简单的来说就是当你startActivity的时候,他就创建一个。

singleTop

这种模式模式从字面意思就能看得出来,就是当前的activity处于栈顶的时候,当你startActivity当前的activity的时候,它不会创建新的activity,而是会复用之前的activity。举个例子,startActivity了一个ActivityA,ActivityA又startActivity了ActivityB,当在ActivityB再次startActivity一个ActivityB的时候,它不会创建一个新的ActivityB,而是复用之前的ActivityB。
这里需要注意的是,只有当前的activity处于栈顶的时候才管用。举个例子:startActivity了一个ActivityA,ActivityA又startActivity了ActivityB,ActivityB又startActivity了ActivityA,那么ActivityA还是会重新创建,而不是复用之前的ActivityA。

singleTask

单一任务。意思就是说当前的activity只有一个实例,无论在任何地方startActivity出来这个activity,它都只存在一个实例。并且,它会将在他之上的所有activity都销毁。通常这个activity都是用来作为MainActivity。因为主页只需要存在一个,然后回到主页的时候可以将所有的activity都销毁起到退出应用的作用。举个例子,startActivity了一个ActivityA,ActivityA的启动模式为singleTask,那么在ActivityA里startActivity了一个ActivityB,在ActivityB里startActivity了一个ActivityC。此时在当前的任务栈中的顺序是,ActivityA->ActivityB->ActivityC。然后在ActivityC里重新startActivity了一个ActivityA,此时ActivityA会将存在于它之上的所有activity都销毁。所以此时任务栈中就只剩下ActivityA了。

singleInstance

这个模式才是重点,也是比较容易入坑的一种启动模式。字面上理解为单一实例。它具备所有singleTask的特点,唯一不同的是,它是存在于另一个任务栈中。上面的三种模式都存在于同一个任务栈中,而这种模式则是存在于另一个任务栈中。

注意事项

以往的理解中,只要在`AndroidManifest.xml`中声明`singleTop`或者`singleInstance`,那么在使用`startActivity`或者`startActivityForResult`的时候,自动就会保证`singleInstance`的情况下只有一个对象,`singleTop`的情况下不会两个相同的`Activity`叠加在一起。

但是现实是让人崩溃的。

使用如下的代码:

package com.mobibrw.myapplication;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    private final static int SINGLE_INSTANCE = 1;
    private final static int SINGLE_TOP = 2;

    private void startSingleInstanceActivity() {
        final Intent intent = new Intent(this, SingleInstanceActivity.class);
        //intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
        startActivityForResult(intent, SINGLE_INSTANCE);
    }

    private void startSingleTopActivity() {
        final Intent intent = new Intent(this, SingleTopActivity.class);
        //intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
        startActivityForResult(intent, SINGLE_TOP);
    }

    private void startSingleInstanceWithFlagsActivity() {
        final Intent intent = new Intent(this, SingleInstanceActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
        startActivityForResult(intent, SINGLE_INSTANCE);
    }

    private void startSingleTopWithFlagsActivity() {
        final Intent intent = new Intent(this, SingleTopActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
        startActivityForResult(intent, SINGLE_TOP);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btnSingleTop = findViewById(R.id.SingleTop);
        btnSingleTop.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startSingleTopActivity();
                startSingleTopActivity();
            }
        });
        Button btnSingleInstance = findViewById(R.id.SingleInstance);
        btnSingleInstance.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startSingleInstanceActivity();
                startSingleInstanceActivity();
            }
        });

        Button btnSingleTopWithFlags = findViewById(R.id.SingleTopWithFlags);
        btnSingleTopWithFlags.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startSingleTopWithFlagsActivity();
                startSingleTopWithFlagsActivity();
            }
        });
        Button btnSingleInstanceWithFlags = findViewById(R.id.SingleInstanceWithFlags);
        btnSingleInstanceWithFlags.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startSingleInstanceWithFlagsActivity();
                startSingleInstanceWithFlagsActivity();
            }
        });
    }
}
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mobibrw.myapplication">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".SingleInstanceActivity"
            android:launchMode="singleInstance"/>
        <activity
            android:name=".SingleTopActivity"
            android:launchMode="singleTop"/>
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

在两次触发`startSingleTopActivity`/`startSingleInstanceActivity`的时候,出现了两个叠加的`Activity`,如下:

$ adb shell dumpsys activity | grep SingleTopActivity 
        Hist #2: ActivityRecord{6f4fc4 u0 com.mobibrw.myapplication/.SingleTopActivity t457}
          Intent { cmp=com.mobibrw.myapplication/.SingleTopActivity }
        Hist #1: ActivityRecord{4a4ec71 u0 com.mobibrw.myapplication/.SingleTopActivity t457}
          Intent { cmp=com.mobibrw.myapplication/.SingleTopActivity }
        Run #1: ActivityRecord{6f4fc4 u0 com.mobibrw.myapplication/.SingleTopActivity t457}
    mResumedActivity: ActivityRecord{6f4fc4 u0 com.mobibrw.myapplication/.SingleTopActivity t457}
  mFocusedActivity: ActivityRecord{6f4fc4 u0 com.mobibrw.myapplication/.SingleTopActivity t457}

可以看到出现两个单独的实例 Hist #2/Hist #1,而不是预期的忽略第二次调用。

在两次触发`startSingleTopWithFlagsActivity`/`startSingleInstanceWithFlagsActivity`的时候,只会出现了一个`Activity`,如下:

$ adb shell dumpsys activity | grep SingleTopActivity
        Hist #1: ActivityRecord{933a335 u0 com.mobibrw.myapplication/.SingleTopActivity t457}
          Intent { flg=0x420000 cmp=com.mobibrw.myapplication/.SingleTopActivity }
        Run #1: ActivityRecord{933a335 u0 com.mobibrw.myapplication/.SingleTopActivity t457}
    mResumedActivity: ActivityRecord{933a335 u0 com.mobibrw.myapplication/.SingleTopActivity t457}
  mFocusedActivity: ActivityRecord{933a335 u0 com.mobibrw.myapplication/.SingleTopActivity t457}

两者的区别就是

intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);

这句代码。

还是学艺不精啊。

完整例子代码,点击此处下载 MyApplication

参考链接


解决SourceTree 3.3.8访问Git库提示“access denied”

使用`SourceTree 3.3.8`,在检出版本库的时候,选择记住密码。过一段时间之后,版本库的密码修改之后,提示`access denied`。

解决方法为删除已经记住的用户名密码,如下:

del "C:\Users\%username%\AppData\Local\Atlassian\SourceTree\passwd"

具体文件位置如下图:

继续阅读解决SourceTree 3.3.8访问Git库提示“access denied”

解决macOS系统curl报告https证书不正确(curl: (60) SSL certificate problem: Invalid certificate chain)

最近在使用`brew`升级`git`的时候,报告如下错误:

$ brew install git -s -d -v --env=std
Warning: You are using macOS 10.11.
We (and Apple) do not provide support for this old version.
You will encounter build failures with some formulae.
Please create pull requests instead of asking for help on Homebrew's GitHub,
Discourse, Twitter or IRC. You are responsible for resolving any issues you
experience while you are running this old version.

Updating Homebrew...
==> Downloading https://www.kernel.org/pub/software/scm/git/git-htmldocs-2.27.0.
curl: (60) SSL certificate problem: Invalid certificate chain
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.
Error: Failed to download resource "git--html"
Download failed: https://www.kernel.org/pub/software/scm/git/git-htmldocs-2.27.0.tar.xz
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/cask).
==> Updated Casks
balenaetcher        gzdoom              poi                 strawberry
cabal               hstracker           stella              trilium-notes

Warning: You are using macOS 10.11.
We (and Apple) do not provide support for this old version.
You will encounter build failures with some formulae.
Please create pull requests instead of asking for help on Homebrew's GitHub,
Discourse, Twitter or IRC. You are responsible for resolving any issues you
experience while you are running this old version.

/usr/local/Homebrew/Library/Homebrew/brew.rb (Formulary::FormulaLoader): loading /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/gettext.rb
/usr/local/Homebrew/Library/Homebrew/brew.rb (Formulary::FormulaLoader): loading /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/pcre2.rb
/usr/bin/curl --disable --globoff --show-error --user-agent Homebrew/2.3.0\ \(Macintosh\;\ Intel\ Mac\ OS\ X\ 10.11.6\)\ curl/7.43.0 --retry 3 --location --silent --head --request GET https://www.kernel.org/pub/software/scm/git/git-htmldocs-2.27.0.tar.xz
==> Downloading https://www.kernel.org/pub/software/scm/git/git-htmldocs-2.27.0.tar.xz
/usr/bin/curl --disable --globoff --show-error --user-agent Homebrew/2.3.0\ \(Macintosh\;\ Intel\ Mac\ OS\ X\ 10.11.6\)\ curl/7.43.0 --retry 3 --location --range 0-1 --dump-header - --write-out \%\{http_code\} --output /dev/null https://www.kernel.org/pub/software/scm/git/git-htmldocs-2.27.0.tar.xz
/usr/bin/curl --disable --globoff --show-error --user-agent Homebrew/2.3.0\ \(Macintosh\;\ Intel\ Mac\ OS\ X\ 10.11.6\)\ curl/7.43.0 --fail --retry 3 --location --remote-time --continue-at 0 --output /Users/xxxx/Library/Caches/Homebrew/downloads/af92f79273b58e47216b46d936335255b08e1eb74369b4714bac1c0e0650b50e--git-htmldocs-2.27.0.tar.xz.incomplete https://www.kernel.org/pub/software/scm/git/git-htmldocs-2.27.0.tar.xz
curl: (60) SSL certificate problem: Invalid certificate chain
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.
Error: Failed to download resource "git--html"
Download failed: https://www.kernel.org/pub/software/scm/git/git-htmldocs-2.27.0.tar.xz
/usr/local/Homebrew/Library/Homebrew/download_strategy.rb:312:in `rescue in fetch'
/usr/local/Homebrew/Library/Homebrew/download_strategy.rb:309:in `fetch'
/usr/local/Homebrew/Library/Homebrew/resource.rb:131:in `fetch'
/usr/local/Homebrew/Library/Homebrew/formula_installer.rb:988:in `each'
/usr/local/Homebrew/Library/Homebrew/formula_installer.rb:988:in `fetch'
/usr/local/Homebrew/Library/Homebrew/cmd/install.rb:329:in `install_formula'
/usr/local/Homebrew/Library/Homebrew/cmd/install.rb:261:in `block in install'
/usr/local/Homebrew/Library/Homebrew/cmd/install.rb:259:in `each'
/usr/local/Homebrew/Library/Homebrew/cmd/install.rb:259:in `install'
/usr/local/Homebrew/Library/Homebrew/brew.rb:110:in `<main>'

手工去下载数据,看到更具体的错误信息,如下:

$ curl  https://www.kernel.org/pub/software/scm/git/git-htmldocs-2.27.0.tar.xz
curl: (60) SSL certificate problem: Invalid certificate chain
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option

解决方法为暂时要求`curl`忽略证书错误问题,如下:

$ touch ~/.curlrc

# 增加禁止校验的参数
$ echo --insecure >> ~/.curlrc

注意,上述配置之后,可能会出现类似如下错误:

curl: (22) The requested URL returned error: 403 [[[!!! BREAKING CHANGE !!!]]] Support for clients that do not support Server Name Indication is temporarily disabled and will be permanently deprecated soon. See https://status.python.org/incidents/hzmjhqsdjqgb and ht

解决方法就是移除上面的配置,参考 OS X EI Capitan curl: (22) The requested URL returned error: 403 [[[!!! BREAKING CHANGE !!!]]] Support for clients that do not support Server Name Indication is temporarily disabled and will be permanently deprecated soon.

参考链接


How to fix curl: (60) SSL certificate: Invalid certificate chain

vue中template的三种写法

第一种(字符串模板写法):

直接写在vue构造器里,这种写法比较直观,适用于html代码不多的场景,但是如果模板里html代码太多,不便于维护,不建议这么写.

<!DOCTYPE html>
<html>
  <!--
    WARNING! Make sure that you match all Quasar related
    tags to the same version! (Below it's "@1.7.4")
  -->

  <head>
     <!--
     <link href="https://cdn.jsdelivr.net/npm/quasar@1.7.4/dist/quasar.min.css" rel="stylesheet" type="text/css">
     -->
     <link href="https://www.mobibrw.com/wp-content/uploads/2020/06/quasar@1.7.4.css" rel="stylesheet" type="text/css">
  </head>

  <body>
    <div id="q-app">

    </div>

    <!-- Add the following at the end of your body tag -->
    <!--
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.7.4/dist/quasar.umd.min.js"></script>
    -->
    <script src="https://www.mobibrw.com/wp-content/uploads/2020/06/vue@2.0.0.js"></script>
    <script src="https://www.mobibrw.com/wp-content/uploads/2020/06/quasar.umd@1.7.4.js"></script>
    
    <script>
      /*
        Example kicking off the UI. Obviously, adapt this to your specific needs.
        Assumes you have a <div id="q-app"></div> in your <body> above
       */
      new Vue({
        el: '#q-app',
        data: function () {
          return {
            version: Quasar.version
          }
        },
        template: `<div class="q-ma-md"> Running Quasar v{{ version }}</div>`
        // ...etc
      })
    </script>
  </body>
</html>

第二种:

直接写在template标签里,这种写法跟写html很像。

<!DOCTYPE html>
<html>
  <!--
    WARNING! Make sure that you match all Quasar related
    tags to the same version! (Below it's "@1.7.4")
  -->

  <head>
     <!--
     <link href="https://cdn.jsdelivr.net/npm/quasar@1.7.4/dist/quasar.min.css" rel="stylesheet" type="text/css">
     -->
     <link href="https://www.mobibrw.com/wp-content/uploads/2020/06/quasar@1.7.4.css" rel="stylesheet" type="text/css">
  </head>

  <body>
    <div id="q-app">
        <template id='template1'>
          <div class="q-ma-md">
            Running Quasar v{{ version }}
          </div>
        </template>
    </div>

    <!-- Add the following at the end of your body tag -->
    <!--
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.7.4/dist/quasar.umd.min.js"></script>
    -->
    <script src="https://www.mobibrw.com/wp-content/uploads/2020/06/vue@2.0.0.js"></script>
    <script src="https://www.mobibrw.com/wp-content/uploads/2020/06/quasar.umd@1.7.4.js"></script>
    
    <script>
      /*
        Example kicking off the UI. Obviously, adapt this to your specific needs.
        Assumes you have a <div id="q-app"></div> in your <body> above
       */
      new Vue({
        el: '#q-app',
        data: function () {
          return {
            version: Quasar.version
          }
        },
        template: '#template1'
        // ...etc
      })
    </script>
  </body>
</html>

第三种:

写在script标签里,这种写法官方推荐,vue官方推荐script中type属性加上"x-template",即:

<!DOCTYPE html>
<html>
  <!--
    WARNING! Make sure that you match all Quasar related
    tags to the same version! (Below it's "@1.7.4")
  -->

  <head>
     <!--
     <link href="https://cdn.jsdelivr.net/npm/quasar@1.7.4/dist/quasar.min.css" rel="stylesheet" type="text/css">
     -->
     <link href="https://www.mobibrw.com/wp-content/uploads/2020/06/quasar@1.7.4.css" rel="stylesheet" type="text/css">
  </head>

  <body>
    <div id="q-app"></div>
	
	<script type="x-template" id="template1">
    	<div class="q-ma-md">
      	  Running Quasar v{{ version }}
    	</div>
    </script>

    <!-- Add the following at the end of your body tag -->
    <!--
    <script src="https://cdn.jsdelivr.net/npm/vue@^2.0.0/dist/vue.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/quasar@1.7.4/dist/quasar.umd.min.js"></script>
    -->
    <script src="https://www.mobibrw.com/wp-content/uploads/2020/06/vue@2.0.0.js"></script>
    <script src="https://www.mobibrw.com/wp-content/uploads/2020/06/quasar.umd@1.7.4.js"></script>
    
    <script>
      /*
        Example kicking off the UI. Obviously, adapt this to your specific needs.
        Assumes you have a <div id="q-app"></div> in your <body> above
       */
      new Vue({
        el: '#q-app',
        data: function () {
          return {
            version: Quasar.version
          }
        },
        template: '#template1'
        // ...etc
      })
    </script>
  </body>
</html>

推荐这个写法的主要原因就可以把模版文件写到另外的一个JS文件里面,然后动态加载,实现模版复用以及文件分离。不至于一个页面里面实现太多的东西,导致页面代码混乱。

参考链接


16款优秀的Vue UI组件库推荐

Vue 是一个轻巧、高性能、可组件化的MVVM库,API简洁明了,上手快。从Vue推出以来,得到众多Web开发者的认可。
在公司的Web前端项目开发中,多个项目采用基于Vue的UI组件框架开发,并投入正式使用。
开发团队在使用Vue.js框架和UI组件库以后,开发效率大大提高,自己写的代码也少了,很多界面效果组件已经封装好了。
在选择Vue UI组件库的过程中,通过GitHub上根据star数量、文档丰富程度、更新的频率以及维护等因素,也收集整理了一些优秀的Vue UI组件库。

PS:国内的UI组件大部分都只有一部分的,常用的头部导航,底部导航,listview,grid表格很多都是没有的。

后面才发现,基于Vue的Quasar Framework 介绍 这个框架UI组件很全面,准备下次使用这个框架了

基于Vue的Quasar Framework 中文网
http://www.quasarchs.com/

quasarframework/quasar: Quasar Framework
https://github.com/quasarframework/quasar

Quasar(发音为/kweɪ.zɑɹ/)是MIT许可的开源框架(基于Vue),可帮助Web开发人员创建:
响应式网站
PWA(Progressive Web App)
通过Apache Cordova构建移动APP(Android,iOS,…)
多平台桌面应用程序(使用Electron)
Quasar允许开发人员编写一次代码,然后使用相同的代码库同时部署为网站、PWA、Mobile App和Electron App。使用最先进的CLI设计应用程序,并提供精心编写,速度非常快的Quasar Web组件。

当使用Quasar时,你不需要像Hammerjs,Momentjs或Bootstrap这样的额外重型库。它拥有这些功能,而且体积很小!

==============

1、 iView UI组件库
iView 是一套基于 Vue.js 的开源 UI 组件库,主要服务于 PC 界面的中后台产品。iView的组件还是比较齐全的,更新也很快,文档写得很详细。有公司团队维护,比较可靠的Vue UI组件框架。iView生态也做得很好,还有开源了一个iView Admin,做后台非常方便。官网上介绍,iView已经应用在TalkingData、阿里巴巴、百度、腾讯、今日头条、京东、滴滴出行、美团、新浪、联想等大型公司的产品中。
iView官网:https://www.iviewui.com/

2、Vux UI组件库
Vux是基于WeUI和Vue2.x开发的移动端UI组件库,主要服务于微信页面。Vux的定位已经很明确了,一是:Vue移动端UI组件库,二是:WeUI的基础样式库。Vux的组件涵盖了所有的WeUI的内容,还扩展了一些常用的组件。比如:Sticky、timeline、v-chart、XCircle。Vux是个人维护的。但是GitHub上star还是很高的,达到13k。在GitHub上看到对issue的关闭还是很迅速的。Vux文档基本的组件用法和效果都讲解到位了。在vux官网上也展示了很多Vux的使用案例。在微信页面开发中,基本没有太多的bug,开发还是比较顺手的。
Vux官网:https://vux.li/

3、Element UI组件库
Element,一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库。Element是饿了么前端开源维护的Vue UI组件库,更新频率还是很高的,基本一周到半个月都会发布一个新版本。组件齐全,基本涵盖后台所需的所有组件,文档讲解详细,例子也很丰富。没有实际使用过,网上的Element教程和文章比较多。Element应该是一个质量比较高的Vue UI组件库。
Element官网:http://element.eleme.io/#/zh-CN

4、Mint UI组件库
Mint UI基于 Vue.js 的移动端组件库,同样出自饿了么前端的项目。Mint UI是真正意义上的按需加载组件。可以只加载声明过的组件及其样式文件。Mint UI 采用 CSS3 处理各种动效,避免浏览器进行不必要的重绘和重排,从而使用户获得流畅顺滑的体验。网上的视频教程很多都是基于Mint UI来讲的,开发移动端web项目还是很方便,文档也很简介明了。很多页面Mint UI组件都已经封装好,基本可以照着例子写,简单的调整一下就可以实现。不过,在GitHub上看最后一次代码提交在2018年1月16日。不知道是项目比较稳定没有更新,还是项目有被废弃的可能。
Mint UI官网:http://mint-ui.github.io/#!/zh-cn

5、Bootstrap-Vue UI组件库
Bootstrap-VUE提供了基于vue2的Bootstrap V4组件和网格系统的实现,完成了广泛和自动化的WAI ARA可访问性标记。Bootstrap 4是最新发布的版本,与 Bootstrap3 相比拥有了更多的具体的类以及把一些有关的部分变成了相关的组件。同时 Bootstrap.min.css 的体积减少了40%以上。Bootstrap4 放弃了对 IE8 以及 iOS 6 的支持,现在仅仅支持 IE9 以上 以及 iOS 7 以上版本的浏览器。想当初刚流行响应式网站的时候,Bootstrap是世界上最受欢迎的建立移动优先网站的框架,Bootstrap可以说风靡全球。就算放在现在很多企业网站都是采用Bootstrap做的响应式。Bootstrap-Vue可以让你在Vue中也实现Bootstrap的效果。
Bootstrap-Vue官网:https://bootstrap-vue.js.org/

6、Ant Design Vue UI组件库
Ant Design Vue是 Ant Design 3.X 的 Vue 实现,开发和服务于企业级后台产品。在GitHub上可以找到几个Ant Design的Vue组件。不过相比较而言,Ant Design Vue更胜一筹。Ant Design Vue共享Ant Design of React设计工具体系,实现了所有Ant Design of React的组件,支持现代浏览器和 IE9 及以上(需要 polyfills)。可以让熟悉Ant Design的在使用Vue时,很容易的上手。
Ant Design Vue官网:https://vuecomponent.github.io/ant-design-vue/docs/vue/introduce-cn/

7、AT-UI UI组件库
AT-UI 是一款基于 Vue.js 2.0 的前端 UI 组件库,主要用于快速开发 PC 网站中后台产品,支持现代浏览器和 IE9 及以上。AT-UI 更加精简,实现了后台常用的组件。
AT_UI官网:https://at-ui.github.io/at-ui/#/zh

8、Vant UI组件库
Vant是一个轻量、可靠的移动端 Vue 组件库。Vant是有赞团队开源的,主要维护也是有赞团队。Vant Weapp 是有赞移动端组件库 Vant 的小程序版本,两者基于相同的视觉规范,提供一致的 API 接口,助力开发者快速搭建小程序应用。截止到目前,Vant已经开源了50+ 个经过有赞线上业务检验的组件。比如:、AddressEdit 地址编辑、AddressList 地址列表、Area 省市区选择、Card 卡片、Contact 联系人、Coupon 优惠券、GoodsAction 商品页行动点、SubmitBar 提交订单栏、Sku 商品规格弹层。如果做商城的,不太在意界面,实现业务逻辑的话,用Vant组件库开发还是很快的。
Vant官网:https://youzan.github.io/vant/#/zh-CN/intro

9、cube-ui UI组件库
cube-ui 是基于 Vue.js 实现的精致移动端组件库。由滴滴内部组件库精简提炼而来,经历了业务一年多的考验,并且每个组件都有充分单元测试,为后续集成提供保障。在交互体验方面追求极致。遵循统一的设计交互标准,高度还原设计效果;接口标准化,统一规范使用方式,开发更加简单高效。支持按需引入和后编译,轻量灵活;扩展性强,可以方便地基于现有组件实现二次开发。
cube-ui官网:https://didi.github.io/cube-ui/#/zh-CN

10、Muse-UI UI组件库
Muse-UI基于 Vue 2.0 优雅的 Material Design UI 组件库。Muse UI 拥有40多个UI 组件,用于适应不同业务环境。Muse UI 仅需少量代码即可完成主题样式替换。Muse UI 可用于开发的复杂单页应用
Muse-UI官网:https://muse-ui.org/#/zh-CN

11、N3-components UI组件库
N3组件库是基于Vue.js构建的,让前端工程师和全栈工程师能快速构建页面和应用。N3-components超过60个组件 组件列表、自定义样式、支持多种模化范式(UMD)、使用ES6进行开发。
N3官网:https://n3-components.github.io/N3-components/component.html

12、Mand Mobile
Mand Mobile是面向金融场景的Vue移动端UI组件库,丰富、灵活、实用,快速搭建优质的金融类产品,让复杂的金融场景变简单。Mand Mobile含有丰富的组件30+的基础组件,覆盖金融场景,极高的易用性组件均有详细说明文档、案例演示,汲取最前沿技术,组件化轻量化实现,兼顾稳定和品质,努力实现金融场景的全覆盖。
Mand Mobile官网:https://didi.github.io/mand-mobile/#/zh-CN/home

下面是1.x的文档和演示地址:(文档地址已经迁移了)

https://mand-mobile.github.io/1x-doc/
https://mand-mobile.github.io/2x-doc/

之前的地址打不开了

13、we-vue UI组件库
we-vue 是一套基于 Vue.js 的移动关组件库,结合 weui.css 样式库,封装了一系列组件,非常适于微信公众号等移动端开发。we-vue 包含35+ 个组件,单元测试覆盖率超 98%,支持 babel-plugin-import,完善的在线文档,详细的在线示例。
we-vue官网:https://wevue.org/

14、veui UI组件库
veui是一个由百度EFE team开发的Vue企业级UI组件库。目前文档还没有,只有demo。
GitHub上说是正在进行的一项工作。那我们就耐心等待吧。
veui官网:https://ecomfe.github.io/veui/components/#/

15、Semantic-UI-Vue UI组件库
Semantic-UI-Vue是基于 Vue.js对Semantic-UI 框架的实现。
Semantic作为一款开发框架,帮助开发者使用对人类友好的HTML语言构建优雅的响应式布局。Semantic-UI-Vue提供了一个类似于 Semantic-UI 的 API 以及一组可定制的主题。
Semantic-UI-Vue官网:https://semantic-ui-vue.github.io/#/
在选择框架的时候一定要根据实际Web开发情况和团队的熟悉程度来选择。一个好的UI组件库对一个Web项目来说很重要

16.Vue.js Material Component Framework — Vuetify.js

https://vuetifyjs.com/zh-Hans

Vuetify完全根据Material Design规范开发。每个组件都是手工制作的,为您的下一个伟大的应用程序带来最好的UI工具。开发并没有停留在Google规范中的核心组件上。通过社区成员和赞助商的支持,更多的组件将被设计并提供给大家享受。

这个主要是国外比较流行的vue ui组件,各种功能都有,有中文翻译的,但有些还是英文的,翻译得不是很好

PS:国内的UI组件大部分都只有一部分的,常用的头部导航,底部导航,listview,grid表格很多都是没有的。

参考链接


读取的XML节点中带有冒号怎么办?

昨天,编程读取XML的时候,遇上了类似下面的一段XML

<a:root xmlns:a="http://ww.abc.com/">
    <a:book>aaaa</a:book>
</a:root>

起初没有特别的留意,于是乎就像平时读取XML一样使用了。

 var ele = from item in xDoc.Descendants("a:book") select item;

但是,运行报错,不允许传入冒号:之类的字符,后来查阅资料发现,节点中,冒号前的a代表是的命名空间,冒号后的才是根节点名称。在Root节点中,也对命名空间进行了声明 xmlns:a="http://ww.abc.com/" ,知道了这么一回事后,再来看看如何去读取,正确的读取是:

 XDocument xDoc = XDocument.Load("a.xml");
 XNamespace n = @"http://www.abc.com";
 var ele = from item in xDoc.Descendants(n + "book")
           select item.Value;

从代码可以看出,我声明了一个XNamespace类型的变量,并且把XML文件中出现的命名空间 http://ww.abc.com/ 赋值给它,然后再读取节点的时候,与真正的节点名称book进行拼接就可以了!

XML中出现命名空间的原因是,当你需要使用多个XML一起工作时,由于两个文档都包含带有不同内容和定义的节点元素,就会发生命名冲突,加上命名空间使用可以避免发生冲突,这与C#编程中类的命名空间的用处差不多。

另外,如果需要了解更多操作XML的可以访问下面这篇文章,写得很详细:

http://www.cnblogs.com/nsky/archive/2013/03/05/2944725.html

参考链接