整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          第3講 小程序框架

          遇見周大俠(網名:程序猿),長沙奧科領航信息技術公司的資深軟件開發工程師。他的軟件開發系列課件和項目,凝聚了多年的專業積累與熱情。每套課件都包含豐富的案例和深入的知識點解析,每一講都配備了精心設計的課后作業,旨在為熱愛編程的你提供最佳編程實踐。是教師備課的得力助手,是學生學習的貼心伴侶,亦是畢業設計的靈感源泉。現在,請搜索微信小程序「奧科領航信息技術 」,讓我們一起深入代碼的世界,探索無限可能!」


          目錄:

          • 小程序框架
          • 邏輯層
          • 視圖層

          一、小程序框架

          1.1 框架概述

          小程序開發框架的目標是通過盡可能簡單、高效的方式讓開發者可以在微信中開發具有原生 APP 體驗的服務。

          整個小程序框架系統分為兩部分:邏輯層(App Service)和 視圖層(View)。小程序提供了自己的視圖層描述語言 WXML 和 WXSS,以及基于 JavaScript 的邏輯層框架,并在視圖層與邏輯層間提供了數據傳輸和事件系統,讓開發者能夠專注于數據與邏輯。

          1.2 數組綁定

          同學們,還記得Vue(實現了MVVM設計模式)中的數據綁定嗎?在Vue中,表單元素和模型實現了雙向的數據綁定,當一端發生改變,另一端會同步改變。微信小程序也實現了類似的功能!

          微信小程序框架的核心是一個響應式的數據綁定系統,可以讓數據與視圖非常簡單地保持同步。當做數據修改的時候,只需要在邏輯層修改數據,視圖層就會做相應的更新。

          示例1:在index頁面的一個view標簽中顯示一個默認的字符串“我愛你”,點擊[確定]按鈕,view標簽顯示為“我恨你”。


          <!-- index.wxml -->
          <!-- 以文本插值{{}}的方式顯示數據 -->
          <!-- view標簽相當于HTML中的div -->
          <view>{{message}}</view>
          <!-- 定義一個按鈕 -->
          <!-- bind:tap事件相當于HTML中的click。changeValue是一個自定義的事件處理函數名稱 -->
          <!-- bind:tap可以寫成bindtap -->
          <button type="primary" bind:tap="changeValue">修改值</button>

          // index.js
          // Page是頁面的入口函數
          Page({
          // 在data選項中定義數據
          data: {
          message: "我愛你"
          },
          // 定義函數
          changeValue: function () {
          // setData()函數的作用:修改data選項中所定義的數據
          // 要修改data選項中所定義的數據,只能通過調用setData()函數來實現!
          this.setData({
          message: "我恨你"
          })
          }
          })

          代碼說明:

          • 我們通過框架將邏輯層數據中的 message與視圖層的 message進行了綁定,所以在頁面一打開的時候會顯示“我愛你”;
          • 當點擊按鈕的時候,觸發bindtap事件,視圖層會發送 changeValue 給邏輯層,邏輯層找到并執行對應的事件處理函數;
          • 回調函數觸發后,邏輯層執行 setData 的操作,將 data 中的 message從“我愛你” 變為“我恨你”,因為該數據和視圖層已經綁定了,從而視圖層會自動改變為“我恨你”!

          小結:

          1. 點擊命令按鈕,會觸發bindtap事件。bindtap事件相當于HTML標簽的onclick事件。bindtap可以寫成bind:tap
          2. 要修改data中的屬性值,必須通過調用setData()函數來修改。

          示例2:在文本框中輸入值,在view中同步顯示。


          <!-- index.wxml -->
          <!-- 定義一個文本框 -->
          <!-- 在文本框中每輸入一個字符,都會觸一次bindinput事件 -->
          <input type="text" bindinput="changeValue" placeholder="請輸入值"/>
          <view>{{message}}</view>

          // index.js
          Page({
          data: {
          message: ""
          },
          // 定義函數
          // 參數e代表一個事件對象,里面封裝了本次事件觸發之后所產生的一些數據
          changeValue: function(e){
          // e.detail.value:獲取文本框中的值
          // detail:詳細;value:值
          console.log(e);
          console.log(e.detail.value);
          this.setData({
          message: e.detail.value
          })
          }
          })

          小結:在文本框中輸入文字,會觸發bindinput事件。bindinput事件相當于HTML中的oninput事件。

          1.3 頁面管理

          框架管理了整個小程序的頁面路由,可以做到頁面間的無縫切換,并給以頁面完整的生命周期。開發者需要做的只是將頁面的數據、方法、生命周期函數注冊到框架中,其他的一切復雜的操作都交由框架處理。

          1.4 基礎組件

          框架提供了一套基礎的組件,這些組件自帶微信風格的樣式以及特殊的邏輯,開發者可以通過組合基礎組件,創建出強大的微信小程序。

          見官網:

          https://developers.weixin.qq.com/miniprogram/dev/component/

          1.5 豐富的API

          框架提供豐富的微信原生API,可以方便的調起微信提供的能力,如獲取用戶信息、本地存儲、支付功能等。

          見官網:

          https://developers.weixin.qq.com/miniprogram/dev/api/

          二、邏輯層

          2.1 注冊小程序

          每個小程序都需要在 app.js 中調用 App() 方法注冊小程序實例,綁定生命周期回調函數、錯誤監聽和頁面不存在監聽函數等。

          App() 必須在 app.js 中調用,必須調用且只能調用一次,不然會出現無法預期的后果。

          App({
          ...
          });

          各個回調函數及其說明請見官方文檔:

          https://developers.weixin.qq.com/miniprogram/dev/reference/api/App.html

          2.2 注冊頁面

          對于小程序中的每個頁面,都需要在頁面對應的 js 文件中進行注冊,指定頁面的初始數據、生命周期回調、事件處理函數等。

          Page({
          ...
          });

          請見官方文檔:

          https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/page.html

          2.3 頁面生命周期

          onLoad->onShow->onReady->onHide->onUnload

          2.4 頁面路由

          從一個頁面跳轉到另一個頁面,叫做頁面路由。

          頁面路由有四個API:

          • navigateTo:導航
          • redirectTo:重定向
          • switchTab:切換Tab頁面
          • reLauhc:重啟

          見官方文檔:

          https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/route.html

          2.4.1 示例1

          默認顯示首頁(index),然后點擊底部導航的日志(log),觀察各個生命周期函數的輸出信息。

          2.4.1.1 準備工作

          (1)app.json

          {
          "pages": [
          "pages/index/index",
          "pages/logs/logs",
          "pages/orders/orders",
          "pages/cart/cart",
          "pages/home/home",
          "pages/a/a"
          ],
          "window": {
          "navigationBarTextStyle": "white",
          "navigationBarTitleText": "中華人民共和國",
          "navigationBarBackgroundColor": "#0000ff"
          },
          "style": "v2",
          "componentFramework": "glass-easel",
          "sitemapLocation": "sitemap.json",
          "lazyCodeLoading": "requiredComponents",
          "tabBar": {
          "list": [{
          "pagePath": "pages/index/index",
          "text": "首頁",
          "iconPath": "./images/1.png",
          "selectedIconPath": "./images/1_1.png"
          },{
          "pagePath": "pages/logs/logs",
          "text": "日志",
          "iconPath": "./images/2.png",
          "selectedIconPath": "./images/2_2.png"
          },{
          "pagePath": "pages/orders/orders",
          "text": "我的訂單",
          "iconPath": "./images/3.png",
          "selectedIconPath": "./images/3_3.png"
          },{
          "pagePath": "pages/cart/cart",
          "text": "購物車",
          "iconPath": "./images/4.png",
          "selectedIconPath": "./images/4_4.png"
          }]
          }
          }

          (2)index.js

          Page({
          onReady: function(){
          console.log("index:ready函數執行了");
          },
          onUnload: function(){
          console.log("index:unload函數執行了");
          },
          onLoad: function(){
          console.log("index:load函數執行了");
          },
          onShow: function(){
          console.log("index:show函數執行了");
          },
          onHide: function(){
          console.log("index:hide函數執行了");
          }
          })

          (3)logs.js

          Page({
          onReady: function(){
          console.log("logs:ready函數執行了");
          },
          onUnload: function(){
          console.log("logs:unload函數執行了");
          },
          onLoad: function(){
          console.log("logs:load函數執行了");
          },
          onShow: function(){
          console.log("logs:show函數執行了");
          },
          onHide: function(){
          console.log("logs:hide函數執行了");
          }
          })

          (4)a.js

          Page({
          onReady: function(){
          console.log("a:ready函數執行了");
          },
          onUnload: function(){
          console.log("a:unload函數執行了");
          },
          onLoad: function(){
          console.log("a:load函數執行了");
          },
          onShow: function(){
          console.log("a:show函數執行了");
          },
          onHide: function(){
          console.log("a:hide函數執行了");
          }
          })

          2.4.1.1 控制臺輸出

          (1)初始顯示首頁的輸出

          (2)切換到底部tab欄的日志的輸出

          從輸出結果可知,原來的首頁只是被隱藏了,并沒有被卸載。

          (3)再切換到首頁

          2.4.2 示例2

          從首頁導航到A頁面。

          // index.js
          Page({
          ...
          navigateToA: function(){
          // 通過導航的方式進行頁面路由
          wx.navigateTo({
          url: '../a/a',
          })
          },
          })

          <!-- index.wxml -->
          <button type="primary" bind:tap="navigateToA">導航到A頁面</button>

          2.4.2 示例3

          從首頁重定向到A頁面。

          // index.js
          Page({
          ...
          redirectToA: function(){
          // 通過導航的方式進行頁面路由
          wx.redirectTo({
          url: '../a/a',
          })
          },
          })

          <!-- index.wxml -->
          ...
          <button type="primary" bind:tap="redirectToA">重定向到A頁面</button>

          更加詳細的路由資料見"小程序路由小結.md"文檔。

          2.5 API

          見官方文檔:

          https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/api.html#API

          前面我們已經用到了wx.navigateTo()、wx.redirectTo()、wx.navigateBack()、wx.switchTab()等API。現在我再舉一個獲取用戶信息API。先看效果:


          <!-- index.wxml -->
          <view class="tip">首頁</view>
          <button type="primary" bindtap="getUserInfo">獲取用戶信息</button>
          <view>{{userInfo.nickName}}</view>
          <view wx:if="{{userInfo.gender}}">{{userInfo.gender == 1? "男" : "女"}}</view>
          <image src="{{userInfo.avatarUrl}}"></image>

          // index.js
          Page({
          data: {
          userInfo: {}
          },
          getUserInfo: function(e){
          wx.getUserProfile({
          desc: "用于完善用戶資料",
          success: (res) => {
          console.log(res.userInfo);
          this.setData({
          userInfo: res.userInfo
          });
          }
          })
          }
          })

          點擊模擬器中的【獲取用戶信息】按鈕,沒有顯示像上圖中那樣的底部彈框,在控制臺輸出的用戶信息如下:

          這是因為從2022年10月26日開始,wx.getUserProfile接口被收回了:

          如果將基礎庫版本調整為2.21.2或者以下,則可以。

          三、視圖層

          框架的視圖層由 WXML 與 WXSS 編寫。

          將邏輯層的數據反映成視圖,同時將視圖層的事件發送給邏輯層。

          • WXML(WeiXin Markup language) 用于描述頁面的結構。
          • WXSS(WeiXin Style Sheet) 用于描述頁面的樣式。

          3.1 wxml

          WXML(WeiXin Markup Language)是框架設計的一套標簽語言,結合基礎組件、事件系統,可以構建出頁面的結構。

          3.1.1 數組綁定

          語法:{{}}

          // index.js
          Page({
          data: {
          message: "初始值"
          }
          })

          <!-- index.wxml -->
          <view>{{message}}</view>

          3.1.2 條件渲染

          語法:wx:if、wx:elif、wx:else

          // index.js
          Page({
          data: {
          week: (new Date()).getDay()
          }
          })

          <!-- index.wxml -->
          <view wx:if="{{week >= 1 && week <= 5}}">
          星期一到星期五,學習時間
          </view>
          <view wx:elif="{{week == 6}}">
          星期六,購物時間
          </view>
          <view wx:else>
          星期天,休息時間
          </view>

          3.1.3 列表渲染

          語法:wx:for

          // index.js
          Page({
          data: {
          students: [{id: 10001, name: "張三"}, {id: 10002, name: "李四"}]
          }
          })

          <!-- index.wxml -->
          <block wx:for="{{students}}">
          <view style="border-bottom: 1px solid #000000">
          <view>序號:{{index}}</view>
          <view>編號:{{item.id}}</view>
          <view>姓名:{{item.name}}</view>
          </view>
          </block>

          代碼說明:

          • <block/> 并不是一個組件,它僅僅是一個包裝元素,不會在頁面中做任何渲染,只接受控制屬性。在上面的例子中,也可以直接將wx:for寫在應用了樣式的那個view上;
          • 默認數組的當前項的下標變量名默認為 index,數組當前項的變量名默認為item;
          • 使用 wx:for-item 可以指定數組當前元素的變量名;
          • 使用 wx:for-index 可以指定數組當前下標的變量名;

          課堂練習:渲染出一個九九乘法口訣表。

          <block wx:for="{{[1,2,3,4,5,6,7,8,9]}}" wx:for-item="i">
          <view>
          <block wx:for="{{[1,2,3,4,5,6,7,8,9]}}" wx:for-item="j">
          <text>{{i}} * {{j}} = {{i * j}}</text>
          </block>
          </view>
          </block>

          關于wxk:key的說明。官方解釋:當數據改變觸發渲染層重新渲染的時候,會校正帶有 key 的組件,框架會確保他們被重新排序,而不是重新創建,以確保使組件保持自身的狀態,并且提高列表渲染時的效率。通俗的理解:在不使用 wx:key的情況下, 如果 array 內的數據發生改變,則會重新創建每個Item對象然后渲染列表,費時費力。而在使用 wx:key的情況下,如果array中的數據發生改變,只是將對應的對象重新排序。未發生變化的對象,不會重新創建。有兩種使用方法:

          • 第一種:wx:key = “字符串或數字”,代表在 for 循環的 array 中 item 的某個 property,該 property 的值需要是列表中唯一的字符串或數字,且不能動態改變。
          • 第二種:保留關鍵字 *this,代表在 for 循環中的 item 本身,這種表示需要 item 本身是一個唯一的字符串或者數字。

          3.2 wxss

          WXSS (WeiXin Style Sheets)是一套樣式語言,用于描述 WXML 的組件樣式。

          WXSS 用來決定 WXML 的組件應該怎么顯示。

          為了適應廣大的前端開發者,WXSS 具有 CSS 大部分特性。同時為了更適合開發微信小程序,WXSS 對 CSS 進行了擴充以及修改。

          與 CSS 相比,WXSS 擴展的特性有:

          • 尺寸單位盡量用rpx:responsive pixel,可以根據屏幕寬度進行自適應
          • 樣式導入使用@import語句可以導入外聯樣式表,@import后跟需要導入的外聯樣式表的相對路徑,用“;”表示語句結束。

          3.3 數據綁定

          在 WXML 中,普通的屬性的綁定是單向的。

          <input type = "text" value="{{value}}" />

          Page({
          data: {
          value: ""
          }
          })

          如果使用 this.setData({ value: 'leaf' }) 來更新 value ,this.data.value 和輸入框的中顯示的值都會被更新為 leaf ;但如果用戶修改了輸入框里的值,卻不會同時改變 this.data.value 。

          如果需要在用戶輸入的同時改變 this.data.value ,需要借助簡易雙向綁定機制。此時,可以在對應項目之前加入 model: 前綴:

          <input model:value="{{value}}" />

          這樣,如果輸入框的值被改變了, this.data.value 也會同時改變。同時, WXML 中所有綁定了 value 的位置也會被一同更新。

          示例:在文本框中輸入值,在view中同步顯示。

          // index.js
          Page({
          data: {
          value: ""
          }
          })

          <!-- index.wxml -->
          <input type = "text" placeholder = "請輸入文字" model:value="{{message}}"/>
          <view>{{message}}</view>

          上面的雙向綁定,只能實現簡單數據類型(比如字符串、數字)的雙向綁定。復雜數據(比如對象、數組)等無法實現雙向綁定,比如:

          // index.js
          Page({
          data: {
          student: {
          id: 1,
          name: "張三"
          }
          }
          })

          <!-- index.wxml -->
          <input type = "text" modal:value = "{{student.name}}">
          <view>{{student.name}}</view>

          一篇文章講解“模型-模板布局之全局配置方式”,本篇文章講解“模板-模板布局之模板標簽方式”。


          模板標簽方式

          這種布局模板不需要在配置文件中設置任何參數,也不需要開啟layout_on,直接在模板文件中指定布局模板即可,相關的布局模板調整也在模板中進行。

          以前面的輸出模板為例,這種方式的入口還是在index/index.html模板,但是我們可以修改下index模板文件的內容,在頭部增加下面的布局標簽(記得首先關閉前面的layout_on設置,否則可能出現布局循環):

          1)基本使用

          ①在index.html模板頭部增加布局標簽

          ②在布局模板view/layout.html中添加布局模板的{__CONTENT__}特定字符串

          預覽:

          {layout name="layout" /}表示當前模板文件需要使用layout.html布局模板文件,而布局模板文件的寫法和上面第一種方式(全局布局方式)是一樣的。當渲染index/index.html模板文件的時候,如果讀取到layout標簽,則會把當前模板的解析內容替換到layout布局模板的{__CONTENT__}特定字符串。

          注意:

          1. 一個模板文件中只能使用一個布局模板,如果模板文件中沒有使用任何layout標簽則表示當前模板不使用任何布局。

          2)使用其他的布局模板

          如果需要使用其他的布局模板,可以改變layout的name屬性,例如:

          ①在index.html模板中設置使用其他布局模板

          ②在view/public/下新建lay.html布局模板

          預覽:

          3)指定要替換的特定字符串

          還可以在layout標簽里面指定要替換的特定字符串:

          ①在index.html模板中指定要替換的特定字符串:

          ②修改public/lay.html布局模板中的特定字符串

          預覽:

          注意:

          1. 布局模板的默認替換的特定字符串為{__CONTENT__}。

          2. 以上設置的特定字符串為[__REPLACE__],那在布局模板中就要使用[__REPLACE__],替換字符串的定界符可以自定義,一般為花括號“{__REPLACE__}”

          ?ThinkPHP5連載為卓象程序員原創,轉載請聯系卓象程序員

          關注卓象程序員,定期發布技術文章

          下一篇講解“模板-模板布局之動態方法布局”

          先使用jQuery選擇器獲取到想要綁定click事件的img元素,然后可以直接綁定click方法,也可以通過bind方法綁定。這里詳細介紹一下bind方法。jQuery 事件 - bind() 方法 —— 定義和用法

          html中如何給圖片添加點擊事件的詳解


          bind() 方法為被選元素添加一個或多個事件處理程序,并規定事件發生時運行的函數。

          jQuery 事件 - bind() 方法 ——將事件和函數綁定到元素

          規定向被選元素添加的一個或多個事件處理程序,以及當事件發生時運行的函數。

          jQuery 事件 - bind() 方法——語法

          1 $(selector).bind(event,data,function)

          jQuery 事件 - bind() 方法——參數描述

          event 必需。規定添加到元素的一個或多個事件。由空格分隔多個事件。必須是有效的事件。

          data 可選。規定傳遞到函數的額外數據。

          function 必需。規定當事件發生時運行的函數。

          實例:


          1 //直接給所有img標簽綁定click事件

          2 $("img").click(function(){

          3 alert('你點擊了圖片');

          4 })

          5

          6 //使用bind方法綁定click事件

          7 $("img").bind("click",function(){

          8 alert('你點擊了圖片');

          9 })


          Html 的img標簽添加點擊事件


          1 package com.topnews;

          2

          3 import java.util.ArrayList;

          4

          5 import android.annotation.SuppressLint;

          6 import android.app.Activity;

          7 import android.app.Fragment;

          8 import android.content.Context;

          9 import android.content.Intent;

          10 import android.graphics.Bitmap;

          11 import android.os.AsyncTask;

          12 import android.os.Bundle;

          13 import android.text.TextUtils;

          14 import android.util.Log;

          15 import android.view.View;

          16 import android.view.ViewGroup.LayoutParams;

          17 import android.webkit.WebChromeClient;

          18 import android.webkit.WebSettings;

          19 import android.webkit.WebView;

          20 import android.webkit.WebViewClient;

          21 import android.webkit.WebSettings.LayoutAlgorithm;

          22 import android.widget.Button;

          23 import android.widget.FrameLayout;

          24 import android.widget.ProgressBar;

          25 import android.widget.TextView;

          26

          27 import com.topnews.base.BaseActivity;

          28 import com.topnews.bean.NewsEntity;

          29 import com.topnews.service.NewsDetailsService;

          30 import com.topnews.tool.BaseTools;

          31 import com.topnews.tool.DataTools;

          32 import com.topnews.tool.DateTools;

          33

          34 @SuppressLint("JavascriptInterface")

          35 public class DetailsActivity extends BaseActivity {

          36 private TextView title;

          37 private ProgressBar progressBar;

          38 private FrameLayout customview_layout;

          39 private String news_url;

          40 private String news_title;

          41 private String news_source;

          42 private String news_date;

          43 private NewsEntity news;

          44 private TextView action_comment_count;

          45 WebView webView;

          46

          47 @Override

          48 protected void onCreate(Bundle savedInstanceState) {

          49 // TODO Auto-generated method stub

          50 super.onCreate(savedInstanceState);

          51 setContentView(R.layout.details);

          52 setNeedBackGesture(true);// 設置需要手勢監聽

          53 getData();

          54 initView();

          55 initWebView();

          56 }

          57

          58 /* 獲取傳遞過來的數據 */

          59 private void getData() {

          60 news = (NewsEntity) getIntent().getSerializableExtra("news");

          61 news_url = news.getSource_url();

          62 news_title = news.getTitle();

          63 news_source = news.getSource();

          64 news_date = 65DateTools.getNewsDetailsDate(String.valueOf(news.getPublishTime()));

          66 }

          67

          68 private void initWebView() {

          69 webView = (WebView) findViewById(R.id.wb_details);

          70 LayoutParams params = new 71LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

          72 if (!TextUtils.isEmpty(news_url)) {

          73 WebSettings settings = webView.getSettings();

          74 settings.setJavaScriptEnabled(true);// 設置可以運行JS腳本

          75 // settings.setTextZoom(120);//Sets the text zoom of the page in

          76 // percent. The default is 100.

          77 settings.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);

          78 // settings.setUseWideViewPort(true); //打開頁面時, 自適應屏幕

          79 // settings.setLoadWithOverviewMode(true);//打開頁面時, 自適應屏幕

          80 settings.setSupportZoom(false);// 用于設置webview放大

          81 settings.setBuiltInZoomControls(false);

          82 webView.setBackgroundResource(R.color.transparent);

          83 // 添加js交互接口類,并起別名 imagelistner

          84 webView.addJavascriptInterface(new 85JavascriptInterface(getApplicationContext()), "imagelistner");

          86 webView.setWebChromeClient(new MyWebChromeClient());

          87 webView.setWebViewClient(new MyWebViewClient());

          88 Log.i("info", "news_url:" + news_url);

          89 Log.i("info", "news_title:" + news_title);

          90 Log.i("info", "news_source:" + news_source);

          91 Log.i("info", "news_date:" + news_date);

          92 new MyAsnycTask().execute(news_url, news_title, news_source + " " + 93news_date);

          94 }

          95 }

          96

          97 private void initView() {

          98 title = (TextView) findViewById(R.id.title);

          99 progressBar = (ProgressBar) findViewById(R.id.ss_htmlprogessbar);

          100 customview_layout = (FrameLayout) 101findViewById(R.id.customview_layout);

          102 // 底部欄目

          103 action_comment_count = (TextView) 104findViewById(R.id.action_comment_count);

          105

          106 progressBar.setVisibility(View.VISIBLE);

          107 title.setTextSize(13);

          108 title.setVisibility(View.VISIBLE);

          109 title.setText(news_url);

          110 action_comment_count.setText(String.valueOf(news.getCommentNum()));

          111 }

          112

          113 @Override

          114 public void onBackPressed() {

          115 super.onBackPressed();

          116 overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right);

          117 }

          118

          119 private class MyAsnycTask extends AsyncTask<string, string,="" string=""> {

          120

          121 @Override

          122 protected String doInBackground(String... urls) {

          123 String data = NewsDetailsService.getNewsDetails(urls[0], urls[1], urls[2]);

          124 Log.i("info", "MyAsnycTask.data:" + data);

          125 return data;

          126 }

          127

          128 @Override

          129 protected void onPostExecute(String data) {

          130 webView.loadDataWithBaseURL(null, data, "text/html", "utf-8", null);

          131 }

          132 }

          133

          134 // 注入js函數監聽

          135 private void addImageClickListner() {

          136 // 這段js函數的功能就是,遍歷所有的img幾點,并添加onclick函數,在還是執137 行的時候調用本地接口傳遞url過去

          138 webView.loadUrl("javascript:(function(){" + "var objs = 139document.getElementsByTagName(\"img\");" + "var imgurl=''; "

          140 + "for(var i=0;i<objs.length;i++) "="" +="" "{"="" 141"imgurl+="objs[i].src+',';"" objs[i].onclick="function()" {="" 142window.imagelistner.openimage(imgurl);="" }="" "}"="" "})()");="" js通信接口="" 143public="" class="" javascriptinterface="" private="" context="" context;="" 144javascriptinterface(context="" context)="" this.context="context;" void="" 145openimage(string="" img)="" string[]="" imgs="img.split(",");" 146arraylist<string=""> imgsUrl = new ArrayList<string>();

          147 for (String s : imgs) {

          148 imgsUrl.add(s);

          149 Log.i("圖片的URL>>>>>>>>>>>>>>>>>>>>>>>", s);

          150 }

          151 Intent intent = new Intent();

          152 intent.putStringArrayListExtra("infos", imgsUrl);

          153 intent.setClass(context, ImageShowActivity.class);

          154 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

          155 context.startActivity(intent);

          156 }

          157 }

          158

          159 // 監聽

          160 private class MyWebViewClient extends WebViewClient {

          161 @Override

          162 public boolean shouldOverrideUrlLoading(WebView view, String url) {

          163 return super.shouldOverrideUrlLoading(view, url);

          164 }

          165

          166 @Override

          167 public void onPageFinished(WebView view, String url) {

          168 view.getSettings().setJavaScriptEnabled(true);

          169 super.onPageFinished(view, url);

          170 // html加載完成之后,添加監聽圖片的點擊js函數

          171 addImageClickListner();

          172 progressBar.setVisibility(View.GONE);

          173 webView.setVisibility(View.VISIBLE);

          174 }

          175

          176 @Override

          177 public void onPageStarted(WebView view, String url, Bitmap favicon) {

          178 view.getSettings().setJavaScriptEnabled(true);

          179 super.onPageStarted(view, url, favicon);

          180 }

          181

          182 @Override

          183 public void onReceivedError(WebView view, int errorCode, String description, 184String failingUrl)

          185 {

          progressBar.setVisibility(View.GONE);

          super.onReceivedError(view, errorCode, description, failingUrl);

          }

          }

          private class MyWebChromeClient extends WebChromeClient {

          @Override

          public void onProgressChanged(WebView view, int newProgress) {

          // TODO Auto-generated method stub

          if (newProgress != 100) {

          progressBar.setProgress(newProgress);

          }

          super.onProgressChanged(view, newProgress);

          }

          }

          }</string></objs.length;i++)></string,>


          // NewsDetailsService.java


          1 package com.topnews.service;

          2

          3 import java.io.IOException;

          4 import org.jsoup.Jsoup;

          5 import org.jsoup.nodes.Document;

          6 import org.jsoup.nodes.Element;

          7

          8 import android.text.TextUtils;

          9

          10 public class NewsDetailsService {

          11 public static String getNewsDetails(String url, String news_title,

          12 String news_date) {

          13 Document document = null;

          14 String data = "" +

          15 "<center><h2 style="'font-size:16px;'">" + news_title + "</h2></center>";

          16 data = data + "<p align="'left'" style="'margin-left:10px'">"

          17 + "<span style="'font-size:10px;'">"

          18 + news_date

          19 + "</span>"

          20 + "</p>";

          21 data = data + "<hr size="'1'">";

          22 try {

          23 document = Jsoup.connect(url).timeout(9000).get();

          24 Element element = null;

          25 if (TextUtils.isEmpty(url)) {

          26 data = "";

          27 element = document.getElementById("memberArea");

          28 } else {

          29 element = document.getElementById("artibody");

          30 }

          31 if (element != null) {

          32 data = data + element.toString();

          33 }

          34 data = data + "";

          35 } catch (IOException e) {

          36 e.printStackTrace();

          37 }

          38 return data;

          39 }

          40 }

          以上就是html中如何給圖片添加點擊事件的詳解的詳細內容,


          主站蜘蛛池模板: 午夜福利一区二区三区高清视频| 无码福利一区二区三区| 日本免费一区二区在线观看| 亚洲日本va一区二区三区| 亚洲一区二区久久| 日韩精品午夜视频一区二区三区| 精品国产日韩亚洲一区91| 国产福利视频一区二区| 精品无码日韩一区二区三区不卡| 精品无码人妻一区二区三区18| 国产一区二区三区免费在线观看| 不卡一区二区在线| 国产色欲AV一区二区三区| 久久精品视频一区二区三区| 精品91一区二区三区| 2020天堂中文字幕一区在线观 | 国产免费无码一区二区| 麻豆精品人妻一区二区三区蜜桃| 午夜精品一区二区三区在线视 | 久久久99精品一区二区| 人妻互换精品一区二区| 日本强伦姧人妻一区二区| 国产精品视频一区二区三区无码| 国产乱码伦精品一区二区三区麻豆| 国产乱码精品一区二区三区香蕉| 色欲AV蜜臀一区二区三区| 久久精品国产亚洲一区二区| 国产丝袜美女一区二区三区| 无码毛片一区二区三区中文字幕 | 国产一区二区三区久久精品| 无码人妻精品一区二区蜜桃百度| 波多野结衣电影区一区二区三区| 亚洲AV无码一区二区一二区| 欧美激情一区二区三区成人| 国内精品一区二区三区东京| 性色AV一区二区三区无码| 国产精品一区二区资源| 精品久久国产一区二区三区香蕉| 久久久久久综合一区中文字幕| 久久久久99人妻一区二区三区| 内射少妇一区27P|