weex 環境搭建

来源:http://www.cnblogs.com/upwgh/archive/2017/12/06/7994854.html
-Advertisement-
Play Games

weex旨在“一次撰寫,多端使用”,意思是,用weex寫的頁面,不論是Android還是iOS甚至web端都可以使用,這樣的話就可以極大的降低開發成本, weex其實就是寫的一個類似於h5的頁面(js編寫),寫完之後將vue文件編譯、部署到Nginx伺服器上(Nginx伺服器後面會講到),這時候在... ...


最近為了項目需要(實際上是為了年底KPI),領導要求用3天時間,學習並使用weex開發一個頁面,說實話,壓力山大。在這之前壓根兒就沒聽說過啊,一臉懵逼

無奈之餘只能Google了,驚喜的發現weex的官網上面是什麼都有啊,環境搭建、weex集成開發、js教程等等還有好多,雙手奉上官網地址:http://weex.apache.org/cn/

既然官網講的這麼全面,我就只說一下我的操作流程;

1、weex環境搭建

首先下載安裝node.js,node.js是weex編譯、打包用的基礎工具,javascript和node.js關係,類似於java與jvm,nodejs去官方網站下載最新穩定版6.xx就可以

安裝好了之後,用以下命令檢查是否安裝成功

node -v
npm -v

出現上圖就說明node.js安裝成功了

npm是nodejs的包管理工具,相當於android中的gradle或者iOS中的cocoapods,但是npm在國內訪問速度較慢,建議大家安裝cnpm,是淘寶的一個npm國內鏡像

安裝完cnpm後執行cnpm install -g weex-toolkit安裝weex-toolkit

$ npm install -g cnpm --registry=https://registry.npm.taobao.org
$ cnpm install -g weex-toolkit

 

命令行敲weex,出現上圖就說明weex-toolkit安裝成功了。

至此weex的安裝就告一段落了,官網上的環境搭建到這裡之後還有幾步,不過我都沒有用上,這裡先記一下,後續需要用到了再補充!!!!!!

2、集成到 Android

接下來就是將weex項目集成到Android項目中去,這塊真是沒有什麼好講的,這塊就和集成第三方sdk一毛一樣的

直接上官網的集成方式:http://weex.apache.org/cn/guide/integrate-to-your-app.html

2-1、個人對weex開發的理解

說一下我對在Android中集成weex的理解吧,可能理解的很淺顯,不喜勿噴!

weex旨在“一次撰寫,多端使用”,意思是,用weex寫的頁面,不論是Android還是iOS甚至web端都可以使用,這樣的話就可以極大的降低開發成本,

weex其實就是寫的一個類似於h5的頁面(js編寫),寫完之後將vue文件編譯、部署到Nginx伺服器上(Nginx伺服器後面會講到),這時候在你的Nginx伺服器下的html文件夾內會生成一個.js的文件,這個.js文件就是你要嵌入到Android項目內的文件,如果一個項目內有很多個weex頁面,就需要編譯部署很多個vue文件,也就是說會在html這個文件夾下生成很多個.js文件,然後你可能會問,那我們要怎麼管理和維護這麼多個.js文件呢?這就需要我們將這些個.js壓縮成一個zip包,把這個壓縮後的zip包個後臺,後臺會生成一個json文件,將這個.json放在Nginx伺服器的html文件夾內,我們需要做的就只是管理和維護這個.json文件就可以了,最後在你的Android項目內,訪問這個Nginx伺服器(伺服器的地址就是你電腦的ip地址),獲取到伺服器上的weex頁面(其實這也能做到預載入的作用)然後進行各種處理和操作;

生成的.json文件就是這麼個東西,在後文要講的獲取頁面,完全靠這裡面的url,非常的重要;

貼一些util代碼吧:

    //在mainActivity或者啟動頁獲取weex相關json文件
    WeexUtils.getPages();

    public static void getPages() {

        new Thread(new Runnable() {
            @Override
            public void run() {
                String url = http://ip地址/後臺生成的.json文件;
                okhttp3.Request request = new okhttp3.Request.Builder()
                        .url(url)
                        .build();
                try {
                    okhttp3.Response response = AlbatrossApplication.getInstance().getClient().newCall(request).execute();
                    String data = response.body().string();
      //okhttp請求.json數據,最後將請求到的數據通過sharedprefer存儲到本地 SharedPreferences pages
= AlbatrossApplication.getInstance().getSharedPreferences("pages", MODE_PRIVATE); pages.edit().putString("pages", data).commit(); downloadBundle(); } catch (IOException e) { e.printStackTrace(); } } }).start(); }

下載weex bundle:

    /**
     * 下載weex bundle
     */
    public static void downloadBundle() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    SharedPreferences pages = AlbatrossApplication.getInstance().getSharedPreferences("pages", MODE_PRIVATE);
                    String pagesData = pages.getString("pages", "");
                    com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(pagesData);
                    String url = jsonObject.getJSONObject("zip").getString("url");
                    String path = AlbatrossApplication.getInstance().getCacheDir() + File.separator + "weex";
                    if (!new File(path).exists()) {
                        new File(path).mkdirs();
                    }
                    File downloadedFile = new File(path, "js_bundle.zip");
                    String localMd5 = WeexUtils.calculateMD5(downloadedFile);
                    if (jsonObject.getJSONObject("zip").getString("md5").equals(localMd5)) {
                        //本地zip和伺服器zip一致,return
                        return;
                    }

                    okhttp3.Request request = new okhttp3.Request.Builder()
                            .url(url)
                            .build();

                    okhttp3.Response response = AlbatrossApplication.getInstance().getClient().newCall(request).execute();
                    BufferedSink sink = Okio.buffer(Okio.sink(downloadedFile));
                    sink.writeAll(response.body().source());
                    sink.close();
                    Log.e("bobo", downloadedFile.length() + "   " + downloadedFile.getAbsolutePath());
                    WeexUtils.unzip(downloadedFile, new File(path));
                    Log.e("bobo 當前目錄文件數", new File(path).listFiles().length + "");

//                    downloadPatch();//下載patch
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

以上的操作就可以獲取到weex頁面了,獲取到了之後就可以開始操作了,這裡我就簡單的舉一個點擊跳轉的例子好了,上代碼

        View view = findviewById(R.id.tv_consist);
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                WXSDKInstance mWXSDKInstance = new WXSDKInstance(getActivity());
                Intent intent = new Intent(getActivity(), WeexActivity.class);
                intent.putExtra("WX_URL",  "/html文件夾下的js文件.js");
                mWXSDKInstance.getContext().startActivity(intent);
            }
        });

跳轉到WeexActivity後,在WeexActivity進行的處理就是將前文存儲在本地的數據解析,根據解析後的數據獲取到指定.js文件的路徑,最後載入這個路徑的頁面,這塊挺亂的,我說的只是一個大概方向,具體的還要看實際情況;

public class WeexActivity extends BaseMainActivity implements View.OnClickListener, IWXRenderListener {
    private String TEST_URL = "http://172.16.36.232/dist/jump.js";
    private WXSDKInstance mWXSDKInstance;
    private FrameLayout mContainer;
    private TextView mTv_title;
    private HashMap<String, String> mLocalBundleBean;
    private TextView mTv_right;
    private boolean isFinish = true;
    private View mTv_left;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        KYApplication.getInstance().addActivity(this);
        setContentView(R.layout.activity_weex);
        initView();

        WXSDKEngine.setActivityNavBarSetter(new NavigatorAdapter());
        mContainer = (FrameLayout) findViewById(R.id.container);
        mWXSDKInstance = new WXSDKInstance(this);
        mWXSDKInstance.registerRenderListener(this);
        /**
         * pageName:自定義,一個標示符號。
         * url:遠程bundle JS的下載地址
         * options:初始化時傳入WEEX的參數,比如 bundle JS地址
         * flag:渲染策略。WXRenderStrategy.APPEND_ASYNC:非同步策略先返回外層View,其他View渲染完成後調用onRenderSuccess。WXRenderStrategy.APPEND_ONCE 所有控制項渲染完後後一次性返回。
         */
        Map<String, Object> options = new HashMap<>();
        String wx_url = getIntent().getStringExtra("WX_URL");
        String title = getIntent().getStringExtra("title");
//        mTv_title.setText(title);
        TEST_URL = wx_url.substring(wx_url.lastIndexOf("/")+1);
        options.put(WXSDKInstance.BUNDLE_URL, TEST_URL);

        //獲取集合,維護文件md5值以及文件對應路徑
        //從json文件里,取出md5對應的文件,有則載入文件,無則載入url
        SharedPreferences pages = getSharedPreferences("pages", MODE_PRIVATE);
        String pageData = pages.getString("pages", "");

        JSONObject jsonObject = JSON.parseObject(pageData);
        JSONArray jsonArray = jsonObject.getJSONArray("pages");

        HashMap<String, PageBean> pageMap = new HashMap<>();//存儲伺服器最新頁面信息
        for (int i = 0; i < jsonArray.size(); i++) {
            PageBean pageBean = JSON.parseObject(jsonArray.getString(i), PageBean.class);
            pageMap.put(pageBean.getPage(), pageBean);
        }

        mLocalBundleBean = new HashMap<>();
        try {
            long time = System.currentTimeMillis();
            getAllFiles(new File(Constant.WEEX_URL));//本地zip包解壓文件md5
            Log.e("bobo", "計算md5總耗時" + (System.currentTimeMillis() - time));
        } catch (Exception e) {
            e.printStackTrace();
        }

        PageBean pageBean = pageMap.get(TEST_URL);//獲取login.js對應的md5、url
        if(pageBean==null){
            Toast.makeText(this,"頁面不存在", Toast.LENGTH_SHORT).show();
            return;
        }
        String localUrl = mLocalBundleBean.get(pageBean.getMd5());
        TEST_URL=pageBean.getUrl();
        if (null != localUrl) {
            mWXSDKInstance.render(TEST_URL, WXFileUtils.loadFileOrAsset(localUrl, this), null, null, WXRenderStrategy.APPEND_ASYNC);
            Log.e("bobo","從本地載入");
        } else {
            mWXSDKInstance.renderByUrl(TEST_URL, TEST_URL, options, null, WXRenderStrategy.APPEND_ONCE);
            Log.e("bobo","從網路載入");
        }
//        mWXSDKInstance.renderByUrl("WXSample", TEST_URL, options, null, WXRenderStrategy.APPEND_ONCE);
    }

    public void initView() {
        mTv_left = findViewById(R.id.tv_left);
        mTv_title = (TextView) findViewById(R.id.tv_title);
        mTv_right = (TextView) findViewById(R.id.tv_right);
        mTv_left.setOnClickListener(this);
        mTv_title.setOnClickListener(this);
        mTv_right.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        if (view.getId() == R.id.tv_left) {
            if(isFinish){
                super.onBackPressed();
            }else {
                mWXSDKInstance.fireGlobalEventCallback("left_click", null);
            }
        } else if (view.getId() == R.id.tv_title) {
//            Toast.makeText(this, "標題點擊了", Toast.LENGTH_SHORT).show();
        } else if (view.getId() == R.id.tv_right) {
            mWXSDKInstance.fireGlobalEventCallback("clickrightitem", null);
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        if (mWXSDKInstance != null) {
            mWXSDKInstance.onActivityStart();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        WXStorageModule wxStorageModule = new WXStorageModule();
        wxStorageModule.setItem("currentPage", WXUtils.getNameFromUrl(TEST_URL),null);

        if (mWXSDKInstance != null) {
            mWXSDKInstance.onActivityResume();

            //發送頁面出現廣播
            Map<String, Object> params = new HashMap<>();
            params.put("page", WXUtils.getNameFromUrl(TEST_URL));
            mWXSDKInstance.fireGlobalEventCallback("appear", params);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mWXSDKInstance != null) {
            mWXSDKInstance.onActivityPause();
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mWXSDKInstance != null) {
            mWXSDKInstance.onActivityStop();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
//        KYApplication.getInstance().deleteActivity(this);
        if (mWXSDKInstance != null) {
            mWXSDKInstance.onActivityDestroy();
        }
    }

    @Override
    public void onViewCreated(WXSDKInstance instance, View view) {
        if (view.getParent() != null) {
            ((ViewGroup) view.getParent()).removeView(view);
        }
        mContainer.addView(view);

        //發送頁面出現廣播
        Map<String, Object> params = new HashMap<>();
        params.put("page", WXUtils.getNameFromUrl(TEST_URL));
        mWXSDKInstance.fireGlobalEventCallback("appear", params);
    }

    @Override
    public void onRenderSuccess(WXSDKInstance wxsdkInstance, int i, int i1) {

    }

    @Override
    public void onRefreshSuccess(WXSDKInstance wxsdkInstance, int i, int i1) {

    }

    @Override
    public void onException(WXSDKInstance wxsdkInstance, String s, String s1) {

    }

    private class NavigatorAdapter implements IActivityNavBarSetter {

        @Override
        public boolean push(String param) {
            return false;
        }

        @Override
        public boolean pop(String param) {
            return false;
        }

        @Override
        public boolean setNavBarRightItem(String param) {
            String title = JSON.parseObject(param).getString("title");

            if(!TextUtils.isEmpty(title) && ("添加報價".equals(title) || "返迴首頁".equals(title))){
                mTv_right.setTextColor(getResources().getColor(R.color.color_5E8BF8));
            }
            mTv_right.setText(title);
            return false;
        }

        @Override
        public boolean clearNavBarRightItem(String param) {
            return false;
        }

        @Override
        public boolean setNavBarLeftItem(String param) {
            return false;
        }

        @Override
        public boolean clearNavBarLeftItem(String param) {
            return false;
        }

        @Override
        public boolean setNavBarMoreItem(String param) {
            return false;
        }

        @Override
        public boolean clearNavBarMoreItem(String param) {
            return false;
        }

        @Override
        public boolean setNavBarTitle(String param) {
            String title = JSON.parseObject(param).getString("title");
            mTv_title.setText(title);
            return false;
        }
    }

    public void getAllFiles(File file) throws Exception {
        File[] files = file.listFiles();
//        long time = System.currentTimeMillis();
        for (int i = 0; i < files.length; i++) {
            if (files[i].isDirectory()) {
                getAllFiles(files[i]);
            } else {
                Log.e("bobo", "name" + files[i].getName() + "  md5" + WeexUtils.calculateMD5(files[i]));
                mLocalBundleBean.put(WeexUtils.calculateMD5(files[i]), files[i].getAbsolutePath());
            }
        }
    }

    /**
     * @return get mWXSDKInstance
     */
    public WXSDKInstance getWXSDKInstance() {
        return mWXSDKInstance;
    }

    @Override
    public void onBackPressed() {
        if(isFinish){
            super.onBackPressed();
        }else {
            mWXSDKInstance.fireGlobalEventCallback("back_click", null);
        }
    }

    /**
     * Sets the isFinish  設置是否直接返回上個頁面
     * You can use getFinish() to get the value of isFinish
     */
    public void setFinish(boolean finish) {
        isFinish = finish;
    }

    public void hideBackButton(){
        mTv_left.setVisibility(View.GONE);
    }
}
View Code

3、Nginx伺服器

終於到最後一步了,Nginx伺服器下載地址:http://nginx.org/en/download.html

我是下載的穩定版

下載完之後解壓到文件夾下,雙擊nginx.exe啟動服務,打開conf這個文件夾,打開nginx.conf這個文件,修改location下的root

3-1、編譯、部署.vue文件

哦。對了,大家應該都是到用webstorm寫vue頁面吧??哈哈哈哈

(1)首次創建項目或者是首次導入項目的時候,需要在控制台執行:cnpm install,這個就類似於Android studio中的sync now。

我們需要通過這個命令將package.json中的所有依賴下載下來;

(2)同樣的,控制台執行:weex compile src/vue文件名 D:\nginx\nginx-1.12.2\html

 意思是將制定的vue文件編譯到nginx伺服器下的指定文件夾內,這時候就會生成一個前文所說到的.js文件。

 

終於全都結束了,這是我今天一天的調研學習的成果,可能有一些地方理解的有偏差或者不對的地方,非常歡迎大家批評指正

如果有任何疑問,歡迎留言~~~~

                                                    2017/12/6 21:05 晚安各位


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 對這個游戲我想大家都不陌生 不管新手還是老手都會遇到難題基本上是處於不會玩的狀態下去亂押註又或者是被某某某帶著跟計劃玩一是直接拉你進群讓你去跟計 劃(沒有長期的計 劃跟計劃死的人很多,你也不例外)二是在微 信 群里發神經的亂下註(或許看到別人買什麼你也跟著買,微信群基本都是托) 那該如何對待這個游戲 ...
  • 通常情況下,ETL工程師創建一個Agent Job來周期性地執行Package,Agent底層調用SSISDB的存儲過程(catalog.start_execution)以同步模式來啟動執行實例,這就意味著,我們可以模擬Agent Job的行為,使用TSQL腳本執行Package。SSIS引擎每執行 ...
  • 瞭解事務和鎖 事務:保持邏輯數據一致性與可恢復性,必不可少的利器。 鎖:多用戶訪問同一資料庫資源時,對訪問的先後次序許可權管理的一種機制,沒有他事務或許將會一塌糊塗,不能保證數據的安全正確讀寫。 死鎖:是資料庫性能的重量級殺手之一,而死鎖卻是不同事務之間搶占數據資源造成的。 不懂的聽上去,挺神奇的,懂 ...
  • 前言: 操作資料庫時候難免會因為“大意”而誤操作,需要快速恢復的話通過備份來恢復是不太可能的,因為需要還原和binlog差來恢復,等不了,很費時。這裡先說明下因為Delete 操作的恢復方法:主要還是通過binlog來進行恢復,前提是binlog_format必須是Row格式,否則只能通過備份來恢復 ...
  • 1. 首先要在實例級別啟用FILESTREAM,打開Sql Server Configuration Manager視窗,雙擊需要設置的SQL SERVER實例進行設置。 2. 需要更改 SQL SERVER 實例的 FILESTREAM 訪問級別,執行以下代碼,並重啟 SQL SERVER 服務: ...
  • [20171206]rman與truncate.txt--//昨天下班在回家的路上,突然想起以前遇到的問題,就是truncate表後,rman做備份時會備份多少truncate表的信息,--//當時在itpub上,還存在討論,就是rman會備份空block嗎?參考鏈接:http://www.itpu ...
  • 待續 ...
  • 一,工程圖。 二,代碼。 ViewController.m ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...