art-template渲染分頁模板

//環境:簡單webpack環境

webpack.config.js

const path = require('path')

const HtmlWebpackPlugin = require('html-webpack-plugin')

 

const VueLoaderPlugin = require('vue-loader/lib/plugin') // 引入這行

 

const webpack = require('webpack')

const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin')

 

//將css樣式單獨抽離成一個文件

let MiniCssExtractPlugin = require('mini-css-extract-plugin');


 

//添加optimize-css-assets-webpack-plugin插件,與uglifyjs-webpack-plugin插件

let OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');

let UglifyJsPlugin = require('uglifyjs-webpack-plugin')

 

const isDev = process.env.NODE_ENV === 'development'

 

const config = {

  mode: 'development',

  entry: path.join(__dirname, './src/index.js'),

  output: {

    filename: 'bundle.js',

    //路徑必須是一個絕對路徑

    path: path.resolve(__dirname, 'dist')

  },

 

  optimization: { //優化項

    minimizer: [

      new UglifyJsPlugin({

        cache: true,

        parallel: true,

        sourceMap: true

      }),

      new OptimizeCSSAssetsPlugin()

    ],

  },

 

  plugins: [

    //process.env.NODE_ENV = development 爲一個變量報錯

    new webpack.DefinePlugin({

      'process.env': {

        NODE_ENV: isDev ? '"development"' : '"production"' //Or JSON.stringify('development')

      }

    }),

    //js打包後自動插入模板

    new HtmlWebpackPlugin({

      filename: 'index.html',

      template: path.resolve(__dirname, './src/index.html'),

      minify: {

        removeAttributeQuotes: true,

        collapseWhitespace: true

      },

      hash: true

 

    }),

    new VueLoaderPlugin(),

 

    new MiniCssExtractPlugin({

      filename: '[name].css',

      chunkFilename: '[id].css',

    })

  ],

 

  module: {

    //規則 css-loader 解析類似import這種語法的語句

    //style-loader 把css插入到head標籤中

    //loader的用法:字符串只用一個loader

    //loader的特點:單一

    //多個loader,需要[]

    //loader順序,從右向左,從下到上執行

    //loader還可以寫出對象方式

    rules: [{

        test: /\.vue$/,

        loader: 'eslint-loader',

        exclude: /node_modules/,

        enforce: 'pre'

      },

      {

        test: /\.vue$/i,

        use: ['vue-loader']

      },

      {

        test: /\.jsx$/,

        loader: 'babel-loader'

      },

 

      {

        test: /\.js$/,

        loader: 'eslint-loader',

        enforce: "pre",

        include: [path.resolve(__dirname, 'src')], // 指定檢查的目錄

        options: { // 這裏的配置項參數將會被傳遞到 eslint 的 CLIEngine

          formatter: require('eslint-friendly-formatter') // 指定錯誤報告的格式規範

        }

      },

      {

        test: /\.js$/i,

        use: {

          loader: 'babel-loader',

          options: {

            presets: [

              '@babel/preset-env'

            ],

            plugins: [

              //注意插件順序

              ["@babel/plugin-proposal-decorators", {

                "legacy": true

              }],

              //https://www.npmjs.com/package/@babel/plugin-proposal-class-properties

              ["@babel/plugin-proposal-class-properties", {

                "loose": true

              }],

              //https://babeljs.io/docs/en/babel-plugin-transform-runtime#docsNav

              "@babel/plugin-transform-runtime",


 

            ],

            include: path.resolve(__dirname, 'src'),

            exclude: /node_modules/

          }

        }

      },

      {

        test: /\.css$/,

        use: [

          // 'style-loader',

          MiniCssExtractPlugin.loader,

          'css-loader',

          'postcss-loader', //給css樣式添加瀏覽器前綴 -moz- ...

        ]

      },

 

      {

        test: /\.(jpg|jpeg|png|svg|gif)$/i,

        use: {

          loader: 'url-loader',

          options: {

            name: '[name].[ext]',

            limit: 10 * 1024

          }

        }

 

      },

 

      {

        test: /\.scss$/i,

        use: [

          // 'style-loader',

           MiniCssExtractPlugin.loader,

           {

            loader:'css-loader',

              options:{

                importLoaders:1

              }

          },

          // {

          //   loader: 'postcss-loader',

          //   options: {

          //     // nables source map support, postcss-loader will use the previous source map given by other loaders and update it accordingly,

          //     // if no previous loader is applied before postcss-loader, the loader will generate a source map for you.

          //     sourceMap: true

          //   }

          // },

 

          {

            loader: "postcss-loader",

            options: {

              ident: 'postcss',

              plugins: [

                require('autoprefixer')({

                  'browsers': ['> 1%', 'last 2 versions']

                }),

              ]

            }

          },


 

          'sass-loader'

        ]

 

      },



 

        {

 

          test: /\.art$/,

 

          loader: 'art-template-loader'

 

      }


 

    ]

  }

}

 

if (isDev) {

  config.module.rules.push({

    test: /\.styl(us)?$/, //rules裏面修改下匹配styl的正則表達式,文件內寫的lang是等於"stylus"的

    use: [

      'style-loader',

      'css-loader',

      {

        loader: 'postcss-loader',

        options: {

          //nables source map support, postcss-loader will use the previous source map given by other loaders and update it accordingly,

          //if no previous loader is applied before postcss-loader, the loader will generate a source map for you.

          sourceMap: true

        }

      },

      'stylus-loader'

    ]

  })

  config.devtool = '#cheap-nodule-eval-source-map' //webpack官方推薦

  config.devServer = {

    port: 8888,

    contentBase: './build', //指定目錄

    progress: true, //打包時顯示進度條

    // open:true, //打包後自動打開瀏覽器

    host: '0.0.0.0', //可localhost、可IP及手機連接wifi訪問等等

    compress: true,

    overlay: {

      warnings: true,

      errors: true

    },

    hot: true //熱替換

  }

 

  config.plugins.push(

    new webpack.HotModuleReplacementPlugin(),

    new webpack.NoEmitOnErrorsPlugin()

  )

} else {

  config.output.filename = '[name].[chunkhash:8].js' //開發環境會報錯

  config.module.rules.push({

    test: /\.styl(us)?$/,

    use: ExtractTextWebpackPlugin.extract({

      fallback: 'style-loader',

      use: [

        'css-loader',

        {

          loader: 'postcss-loader',

          options: {

            //nables source map support, postcss-loader will use the previous source map given by other loaders and update it accordingly,

            //if no previous loader is applied before postcss-loader, the loader will generate a source map for you.

            sourceMap: true

          }

        },

        'stylus-loader'

      ]

    })

  })

 

  config.plugins.push(

    new ExtractTextWebpackPlugin({

      //因爲webpack4包含了contenthash這個關鍵字段,所以extarct-text-webpack-plugin中不能使用contenthash

      //解決:使用md5:contenthash:hex:8替代

      // filename:'styles.[contentHash:8].css'

      filename: 'styles.[md5:contenthash:hex:8].css'

    })

  )

}


 

module.exports = config

 

// 構建分頁邏輯所需要的數據(代碼來自慕課網某課程)

// art-template的使用原則:不要在裏面拼接大段的HTML代碼。

// 類似本利中的分頁組件,最好是構造一份適合Handlebars的數據,然後傳給它,來生成html。

formatPag.js

const formatPag = function (pagData) {

  var arr = []

  var total = parseInt(pagData.totalCount)

  var cur = parseInt(pagData.curPage)

  // 處理首頁的邏輯:<<

  var toLeft = {}

  toLeft.index = 1 // index代表點擊按鈕的時候可以跳轉到的頁面

  toLeft.text = '&laquo;' // text代表button的文本

  if (cur !== 1) {

    toLeft.clickable = true

  }

  arr.push(toLeft)

  // 處理到上一頁的邏輯

  var pre = {}

  pre.index = cur - 1

  pre.text = '&lsaquo;'

  if (cur !== 1) {

    pre.clickable = true

  }

  arr.push(pre)

 

  var pag

 

  // 處理到cur頁前的邏輯

  if (cur <= 5) {

    for (var i = 1; i < cur; i++) {

      pag = {}

 

      pag.text = i

 

      pag.index = i

 

      pag.clickable = true

 

      arr.push(pag)

    }

  } else {

    // 如果cur>5,那麼cur前的頁要顯示爲...

    pag = {}

 

    pag.text = 1

 

    pag.index = 1

 

    pag.clickable = true

 

    arr.push(pag)

 

    pag.text = '...'

 

    arr.push(pag)

 

    // 當前頁前面2個頁數顯示出來

 

    for (var j = cur - 2; j < cur; j++) {

      pag = {}

 

      pag.text = j

 

      pag.index = j

 

      pag.clickable = true

 

      arr.push(pag)

    }

  }

 

  // 處理當前頁

  pag = {}

 

  pag.text = cur

 

  pag.index = cur

 

  pag.cur = true

 

  arr.push(pag)

 

  // 處理cur頁後的邏輯

 

  if (cur >= total - 4) {

    for (var k = cur + 1; k <= total; k++) {

      pag = {}

 

      pag.text = k

 

      pag.index = k

 

      pag.clickable = true

 

      arr.push(pag)

    }

  } else {

    // 如果cur < total - 4, 那麼cur後的頁面顯示爲...

 

    // 顯示以當前頁後面的2個頁數

 

    for (var m = cur + 1; m <= cur + 2; m++) {

      pag = {}

 

      pag.text = m

 

      pag.index = m

 

      pag.clickable = true

 

      arr.push(pag)

    }

 

    pag = {}

 

    pag.text = '...'

 

    arr.push(pag)

 

    pag = {}

 

    pag.text = total

 

    pag.index = total

 

    pag.clickable = true

 

    arr.push(pag)

  }

 

  // 處理到下一頁的邏輯

 

  var next = {}

 

  next.index = cur + 1

 

  next.text = '&rsaquo;'

 

  if (cur !== total) {

    next.clickable = true

  }

 

  arr.push(next)

 

  // 處理到尾頁的邏輯

 

  var toRight = {}

 

  toRight.index = total // index代表點擊按鈕的時候可以跳轉到的頁面

 

  toRight.text = '&raquo;' // text代表button的文本

 

  if (cur !== total) {

    toRight.clickable = true

  }

 

  arr.push(toRight)

 

  return arr

}

 

export default formatPag

 

//page.art

<ul>
    {{if data && data.length>0}}
    {{each data}}
    <li data-id={{$value.index}} {{if $value.cur}} class="cur" {{/if}} {{if $value.clickable}} class="clickable" {{/if}}>{{# $value.text}}</li>
    {{/each}}
     {{else }}
        {{/if}}
</ul>

 

//page.js

const $ = require('jquery');

const page = require('./page.art');

$.getJSON('http://imoocnote.calfnote.com/inter/getClasses.php', {

    curPage: 1

}, function (data) {

 

    console.log(JSON.stringify(formatPag(data)));

    var html = page({"data":formatPag(data)});

    $("#page").html(html);

    

});

 

index.js

 

import Vue from 'vue'

import App from './app.vue'

// img.src = './meinv.png';就是一個普通字符串

import beauty from './images/profile.jpg'

// import axios from 'axios'

 

import formatPag from './formatPag.js'

 

require('@primer/css/buttons/index.scss')

require('@primer/css/utilities/index.scss')

require('./style/page.css')

 

const img = new Image()// 把圖片引入,返回一個新的圖片地址

img.src = beauty

 

const root = document.createElement('div')

document.body.appendChild(root)

 

document.body.appendChild(img)

 

const $ = require('jquery')

 

const page = require('./tpl/page.art')

 

console.log(formatPag)

 

$.getJSON('http://imoocnote.calfnote.com/inter/getClasses.php', {

  curPage: 1

}, function (data) {

  console.log(JSON.stringify(formatPag(data)))

  var html = page({ data: formatPag(data) })

  $('#pag').html(html)

})

 

new Vue({

  // 通過h把App組件掛載到html裏面,這裏只是聲明瞭渲染的是組件App的內容,還需通過$mount掛載到html的一個節點上面

  render: (h) => h(App)

}).$mount(root)

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章