Vue: Excel表格内容如何用 JS 进行输出

thbcm阅读(227)

将Excel表格的内容用js进行输出

问题:

在vue项目中使用js获取Excel表格里面的数据

解决方法:

第一步:下载插件
cnpm i xlsx
第二步:新建一个js文件,将方法进行写入,并导出

import XLSX from 'xlsx'

function get_header_row (sheet) {

    const headers = []

    const range = XLSX.utils.decode_range(sheet['!ref'])

    let C

    const R = range.s.r /* start in the first row */

    for (C = range.s.c; C <= range.e.c; ++C) {

        /* walk every column in the range */

        var cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })] /* find the cell in the first row */

        var hdr = 'UNKNOWN ' + C // <-- replace with your desired default

        if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)

        headers.push(hdr)

    }

    return headers

}

const read = (data, type) => {

    const workbook = XLSX.read(data, { type: type })

    const firstSheetName = workbook.SheetNames[0]

    const worksheet = workbook.Sheets[firstSheetName]

    const header = get_header_row(worksheet)

    const results = XLSX.utils.sheet_to_csv(worksheet)

    return { header, results }

}

export { read }

第三步:在项目里使用,获取到表格里的数据

<template>

    <div>

        <el-button class="exportExcel"

                   @click="exportExcel">导入</el-button>

        <input type="file"

               ref="keyWordData"

               @change='handleBeforeUpload'>

    </div>

</template>

<script>

import { read } from '@/utils/excel'

export default {

    data () {

        return {

            allData: [],

        }

    },

    methods: {

        exportExcel () {

            this.$refs['keyWordData'].click()

        },

        handleBeforeUpload (event) {

            let file = event.target.files[0]

            const reader = new FileReader()

            reader.readAsArrayBuffer(file)

            reader.onload = e => {

                const data = e.target.result

                const { results } = read(data, 'array')

                if (results) {

                    let arr = this.$CommUtils.deepClone(results.split('\n'))

                    arr = arr.filter(item => {

                        return item

                    })

                    this.keyWordData = arr

                    console.log(arr)

                }

            }

        },

    },

}

</script>

arr是一个数组,每个元素是一个字符串,是用逗号分隔的,如果想得到其中的某个点,需要使用split进行切割成数组,然后再新建一个空数组,把需要的数据来进行push。

推荐好课:Vue 3.0 新特性全面解析(走在技术前沿)小白学前端:Vue.js 2.0进阶

厌倦了写活动页?快来撸一个页面生成器吧!

thbcm阅读(205)

作者:muwoo

原文:https://github.com/muwoo/rose

Rose

活动页构建利器,用于快速搭建活动页

前言

如果你经常接触一些公司的活动页,可能会经常头疼以下问题:这些项目周期短,需求频繁,迭代快,技术要求不高,成长空间也小。但是我们还是马不停蹄的赶着产品提来的一个个需求,随着公司规模的增加,我们不可能无限制的增加人手不断地重复着这些活动。这里我就不具体介绍一些有的没的的一些概念了,因为要介绍的概念实在太多了,作为一个前端的我们,直接上代码撸就好了!!!!

目标

我们的目标是实现一个页面制作后台,在后台中我们可以对页面进行 组件选择 --> 布局样式调整 --> 发布上线 --> 编辑修改这样的流程操作。

架构设计

首先是要能提供组件给用户进行选择,那么我们需要一个组件库,然后需要对选择的组件进行布局样式调整,所以我们需要一个页面编辑后台接着我们需要将编辑产出的数据渲染成真实的页面,所以我们需要一个node服务和用于填充的template 模板。发布上线,这个直接对接各个公司内部的发布系统就好了,这里我们不做过多阐述。最后的编辑修改功能也就是针对配置的修改,所以我们需要一个数据库,这里我选择的是用了mysql 。当然你也可以顺便做做权限管理,页面管理….等等之类的活。 啰嗦了这么长,我们来画个图,了解下大概的流程:

开撸

组件的实现

首先我们来实现组件这一部分,因为组件关联着后台编辑的预览和最后发布的使用。组件设计我们应该尽量保持组件的对外一致性,这样在进行渲染的时候,我们可以提供一个统一的对外数据接口。这里我们的技术选型是基于 Vue 的,所以下面的代码部分也主要是基于 Vue 的,但是万变不离其宗,其他语言也类似。

根据上图,我们的组件是会被一个个拆分单独发布到 npm仓库的,为什么这么设计呢?其实之前也考虑过设计成一个组件库,所有组件都包含在一个组件库内,这样只需要发布一个组件库包,用的时候按需加载就好了。后来在实践的过程中发现这样并不合适协同开发,其他前端如果想贡献组件,接入的改造成本也很大。举个例子:小明在业务中写了个Button组件,这个组件经常会被其他项目复用,他想把这个组件贡献到我们的系统中,被模板使用,如果是一个组件库的话,他首先得拉取我们组件库的代码,然后按照组件库的规范格式进行提交。这样一来,偷懒的小明可能就不太愿意这么干,最爽的方法当然是在本地构建一个npm库,开发选用的是用TypeScript还是其他的我们不关心,选用的 Css 预处理器我们也不关心,甚至编码规范的ESLint我们也不关心。最后只需通过编译后的文件即可。这样就避免了一个组件库的约束。依托于NPM完善的发布/拉取,以及版本控制机制,可以让我们少做一些额外的工作,也可以快速的把平台搭建起来。

说了这么多,代码呢?,我们以一个Button为例,我们对外提供这样的形式组件:

<template>
  <div :style="data.style.container" class="w_button_container">
    <button :style="data.style.btn"> {{data.context}}</button>
  </div>
</template>
<script>


export default {
  name: 'WButton',
  props: {
    data: {
      type: Object,
      default: () => {}
    }
  }
}
</script>

可以看到我们只对外暴露了一个props,这样做法的好处是可以统一组件对外暴露的数据,组件内部爱怎么玩怎么玩。注意,这里我们也可以引入一些第三方组件库,比如mint-ui之类的。

后台编辑的实现

在写代码前,我们先考虑一下需要实现哪些功能:

  1. 一个属性编辑区,提供给使用者编辑组件内部props的功能
  2. 一个组件选择区,提供使用者选择需要的组件
  3. 一个组件预览区,提供使用者拖拽排序页面预览的功能
编辑区的实现

按照顺序,我们先来实现组件的属性编辑功能。我们要考虑,一个组件暴露出哪些可配置的信息。这些可配置的信息如何同步到后台编辑区,让使用者进行编辑,一个按钮的可配置信息可能是这样:

如果把这些配置全部写在后台库里面,根据当前选择的组件加载不同的配置,维护起来会相当麻烦,而且随着组件数量的增加,也会变得臃肿,所以我们可以将这些配置存储在服务端,后台只需要根据存储的规则进行解析便可,举个例子,我们其实可以存储这样的编辑配置:

[
  {
    "blockName": "按钮布局设置", 
    "settings": {
      "src": {
        "type": "input",  
        "require": true,
        "label": "按钮文案"
      }
    }
  }
]

我们在编辑后台,通过接口请求到这些配置,便可以进行规则渲染:

    /**
     * 根据类型,选择创建对应的组件
     * @param {VNode} vm
     * @returns {any}
     */
    createEditorElement (vm: VNode) {
      let dom = null
      switch (vm.config.type) {
        case 'align':
          dom = this.createAlignElement(vm)
          break;
        case 'select':
          dom = this.createSelectElement(vm)
          break;
        case 'actions':
          dom = this.createActionElement(vm)
          break;
        case 'vue-editor':
          dom = this.createVueEditor(vm)
          break;
        default:
          dom = this.createBasicElement(vm)
      }
      return dom
    }

组件选择功能

首先我们需要考虑的是,组件怎么进行注册?因为组件被用户选用的时候,我们是需要渲染该组件的,所以我们可以提供一段 node 脚本来遍历所需组件,进行组件的安装注册:

// 定义渲染模板和路径
var OUTPUT_PATH = path.join(__dirname, '../packages/index.js');
console.log(chalk.yellow('正在生成包引用文件...'))
var INSTALL_COMPONENT_TEMPLATE = '    {{name}}';
var IMPORT_TEMPLATE = 'import {{componentName}} from \\\\'{{name}}\\\\'';
var MAIN_TEMPLATE = `/* Automatic generated by './compiler/build-entry.js' */


{{include}}


const components = [
{{install}}
]


const install = function(Vue) {
    components.map((component) => {
        Vue.component(component.name, component)
    })
}


/* istanbul ignore if */
if (typeof window !== 'undefined' && window.Vue) {
    install(window.Vue)
}


export {
    install,
{{list}}
}
`;
// 渲染引用文件
var template = render(MAIN_TEMPLATE, {
  include: includeComponentTemplate.join(endOfLine),
  install: installTemplate.join(`,${endOfLine}`),
  version: process.env.VERSION || require('../package.json').version,
  list: listTemplate.join(`,${endOfLine}`)
});


// 写入引用
fs.writeFileSync(OUTPUT_PATH, template);

最后渲染出来的文件大概是这样:

import WButton from 'w-button'
const components = [
    WButton
]
const install = function(Vue) {
    components.map((component) => {
        Vue.component(component.name, component)
    })
}
/* istanbul ignore if */
if (typeof window !== 'undefined' && window.Vue) {
    install(window.Vue)
}
export {
    install,
    WButton
}

这个也是组件库的通用写法,所以这里的思想就是把发布到npm上的组件,进行聚合,聚合成一个组件包引用,我们在后台编辑的时候,是需要全量引入的:

import * as W_UI from '../../packages'


Vue.use(W_UI)

这样,我们组件便注册完了,组件选择区,主要是提供组件的可选项,我们可以遍历组件,提供一个个 List 让用户选择,当然如果我们每个组件如果只提供一个组件名,用户可能并不知道组件长什么样,所以我们最好可以提供一下组件长什么样的缩略图。这里我们可以在组件发布的时候,也通过 node 脚本进行。这里要实现的代码比较多,我就大致说一下过程,因为也不是核心逻辑,可有可无,只能说有了体验上会好一点:

  1. 用户启用 dev-server 进行代码编写测试
  2. server 脚本使用 Chrome 工具 puppeteer,调整页面到手机端模式, 进行当前 dev-server 截图。
  3. 生成截图文件,上传到node服务,关联组件

这样,就可以在加载组件选择区的时候,为组件附上缩略图。

组件预览区

当用户在选择区选择了组件,我们需要展示在预览区域,那么我们怎么知道用户选择了哪些组件呢?总不能提前全部把组件写入渲染区域,通过 v-if来判断选择吧?当然没有这么蠢,Vue 已经提供了动态组件的功能了:

<div 
   :class="[index===currentEditor ? 'active' : '']" 
   :is="select.name" 
   :data="select.data">
</div>

为什么我们不用缩略图代替真实组件?一方面生成的缩略图尺寸存在问题,另一方面,我们需要编辑的联动性,就是编辑区的编辑需要及时的反馈给用户。

额外的问题

说了这么多,貌似一切都很顺利,但是这样在实践的时候,发现了存在一个明显的问题就是:我们中间的预览区域其实就是为了尽可能模拟移动端页面效果。但是如果我们加入了一些包含类似 position: fixed 样式的组件,会发现样式上就出现了明显的问题。典型的比如Dialog Loading 等。 所以我们参考了 m-ui组件库的设计,将中间预览操作容器展示为一个iframe。将iframe大小调整为375 * 667,模拟 iPhone 6 的手机端。这样就不会存在样式问题了。可是这样又出现了另一个难点,那就是左侧的编辑数据如何及时的反应到iframe中?没错,就是postMessgae,大致思路如下:

利用 vuex 做数据存储池,所有的变化,通过 postMessgae进行同步,这样我们只用确保数据池中的数据变化,便可以映射到渲染层的变化。比如,我们在预览区进行了组件选择和拖拽排序,那么我们只需通过vuex出发同步信息便可:

// action.ts
const action = {
  setCurrentPage ({commit, state}, page: number) {
      // 更新当前store
      commit('setCurrentPage',page)
      // 对应postMessage
      helper.postMsgToChild({type: 'syncState', value: state})
    },
  // ...
}

Template 模板的实现

模板的设计实现,我参考了 Vue-cli 2.x 版本的思想,把这里的模板,存在了对应的 git 仓库中。当用户需要进行页面构建的时候,直接从 git 仓库中拉取对应的模板即可。当然拉取完,也会缓存一份在本地,以后渲染,直接从本地缓存中读取即可。我们现在把中心放在模板的格式和规范上。模板我们采用什么样的语法无所谓,这里我才用了和 Vue-cli一样的Handlerbars引擎。这里直接上我们模板的设计:

<template>
  <div class="pg-index" :style="{backgroundColor: '{{bgColor}}'}">
      <div class="main-container" :style="{
        backgroundColor: '{{bgColor}}',
        backgroundImage: '{{bgImage}}' ? 'url({{bgImage}})' : null,
        backgroundSize: '{{bgSize}}',
        backgroundRepeat: 'no-repeat'
      }">
        {{#components}}
          <div class="cp-module-editor {{className}} {{data.className}}">
            <{{name}} class="temp-component" :data="{{tostring data}}" data-type="{{upcasefirst name}}"></{{name}}>
          </div>
        {{/components}}
      </div>
  </div>
</template>


<script>
    {{#noRepeatCpsName}}
  import {{upcasefirst this}} from '{{this}}'
    {{/noRepeatCpsName}}
export default {
  name: '{{upcasefirst repoName}}',
  components: {
    {{#noRepeatCpsName}}
      {{upcasefirst this}},
    {{/noRepeatCpsName}}
  }
}
</script>

为了简化逻辑,我们把模板都设计成流式布局,所有组件一个个堆叠往下顺序排列。这个文件便是我们vue-webpack-simple的模板中的App.vue。我们对其进行了改写。这样在数据填充万,便可以渲染出一个 Vue 单文件。这里我只举着一个例子,我们还可以实现多页模板等等复杂的模板,根据需求拉取不同的模板即可。

Node 渲染服务

当后台提交渲染请求的时候,我们的 node 服务所做的工作主要是:

  1. 拉取对应模板
  2. 渲染数据
  3. 编译

拉取也就是去指定仓库中通过download-git-repo插件进行拉取模板。编译其实也就是通过metalsmith静态模板生成器把模板作为输入,数据作为填充,按照handlebars的语法进行规则渲染。最后产出build构建好的目录。在这一步,我们之前所需的组件,会被渲染进package.json文件。我们来看一下核心代码:

// 这里就像一个管道,以数据入口为生成源,通过renderTemplateFiles编译产出到目标目录
function build(data, temp_dest, source, dest, cb) {
  let metalsmith = Metalsmith(temp_dest)
    .use(renderTemplateFiles(data))
    .source(source)
    .destination(dest)
    .clean(false)


  return metalsmith.build((error, files) => {
    if (error) console.log(error);
    let f = Object.keys(files)
      .filter(o => fs.existsSync(path.join(dest, o)))
      .map(o => path.join(dest, o))
    cb(error, f)
  })
}




function renderTemplateFiles(data) {
  return function (files) {
    Object.keys(files).forEach((fileName) => {
      let file = files[fileName]
      // 渲染方法
      file.contents = Handlebars.compile(file.contents.toString())(data)
    })
  }
}

最后我们得到的是一个 Vue 项目,此时还不能直接跑在浏览器端,这里就涉及到当前发布系统所支持的形式了。怎么说?如果你的公司发布系统需要在线编译,那么你可以把源文件直接上传到 git 仓库,触发仓库的 WebHook 让发布系统替你发掉这个项目即可。如果你们的发布系统是需要你编译后提交编译文件进行发布的,那么你可以通过 node 命令,进行本地构建,产出 HTML CSS JS 。直接提交给发布系统即可。 到这里,我们的任务就差不多了~具体的核心实心大多已经阐述清楚,如果实现当中有什么问题和不妥,也欢迎一起探讨交流!!

题外话

实现这样一套页面构建系统,其实我这里简化了很多东西,旨在给大家提供一种思路。另外,其实我们的页面全部在服务端构建的时候产出,我们可以再服务端这一层做很多工作,比如页面的性能优化,因为页面数据我们全部都有,我们也可以做页面的预渲染,骨架屏,ssr ,编译时优化等等。而且我们也可以对产出的活动页做数据分析~有很多想象的空间。

雷军:2021年的第一件大事,给工程师发百万美金大奖

thbcm阅读(196)

  • 作者:雷军
  • 来源:雷军公众号

今天,我们给 2021 年开了一个好头,办了开年第一件大事:就是颁发“百万美金技术大奖”。而且这一回,我们一次发了两个百万美金技术大奖。祝贺小米秒充团队、MIUI隐私保护团队,我为你们的创新和勇气感到骄傲和自豪!

这两个项目,一个是在行业绝对领先的硬件技术,一个是让米粉竖起大拇指的软件技术,不相上下,都是业内顶尖的创新,都倾注了小米工程师巨大的心血,都非常受米粉欢迎,都有良好的口碑。因此,今年百万美金大奖就发两个,软硬兼修,好事成双!

今年是我们第二次颁发百万美金大奖。小米集团副总裁、集团技术委员会主席崔宝秋博士跟我说,在这次评审过程中,涌现了一大批出类拔萃的硬核技术。看到越来越多的幕后英雄走上前台,我感到由衷的高兴。你们代表了一万多名小米的工程师,代表了这个英雄的群体,感谢你们为小米所做的一切!在此,我想跟大家分享一下,小米工程师们的工作成果。

120W有线秒充

三大创新引领充电行业未来

小米10至尊纪念版最早采用了120W秒充技术,也是全球首个量产的120W快充产品充满4500mAh的手机仅需要23分钟。由于我们是第一个大胆做120W秒充的,等于是行走在技术的无人区,这支年轻的技术团队,在硬件架构、充电算法和安全策略这三大核心领域做出了了不起的创新。

在硬件架构上小米至少实现了五项行业首次:首创120W+50W+10W三重快充架构;首个4:2直充架构,采用自主定制充电芯片;首创蝶式双电芯结构电池;首个6C高性能石墨烯电芯体系;首个量产的高性能120W充电器。

不只硬件突破,小米在充电算法上也做出了创新。小米秒充团队在行业首创了充电仿真评估方法,可以提前预估120W充电性能,并针对瓶颈问题优化设计;为了提升充电速度,小米秒充团队还首创了多级递变电流调控技术,充电速度相比传统方案提升了10%以上。

充电最关键的是安全。在安全策略方面,提供了34重安全保护策略。其中充电器端7项,主板端18项,电池端9项。这样极致的保护也获得了德国莱茵TÜV安全快充系统3.0认证。此外,小米还采用了独立MCU+算法,进一步提升充电安全。

MIUI隐私保护

全方位国际领先

2020年,小米在一年之内发布了MIUI 12和MIUI 12.5两个大版本,其中安全与隐私能力的突破性提升,获得了用户和国家机构的高度认可。众所周知,隐私保护已是全球关注的焦点,而安卓作为开放系统,依然有很多恶意的APP在肆无忌惮地窃取用户的隐私。隐私保护是每个用户的基本需求。不管是中国用户,还是外国用户,我们都应该坚持用最高的标准,给他们提供同等的、极致的隐私保护。

MIUI安全与隐私团队就在这样的条件下,打造了全球最领先的隐私保护能力。小米在隐私保护方面,不仅有最高的标准、最严苛的流程管理、最极致的“从设计着手的隐私保护”理念,更重要的是我们有最硬核的隐私保护技术。

MIUI 12率先推出了隐私保护三叉戟:照明弹、拦截网和隐匿面具。照明弹,就是记录系统所有事件,并通知用户应用的敏感行为,把知情权交给用户。拦截网和隐匿面具则是把选择权和管理权交给了用户,让用户对应用的权限管理更加有力。统计数据表明,自MIUI 12于去年5月发布后,APP访问各类隐私权限频次大幅下降了90%以上。此外,小米参与了百余项行业标准的建设,在《移动智能终端安全能力技术要求》2020送审稿中,“照明弹”、“应用行为记录”等功能将被列入手机入网标准安全能力一级,成为手机入网的必要条件。

不久前发布的MIUI 12.5 ,小米将隐私保护再次向前推进了一大步,做到了全球领先。小米首推了全球最全面的剪切板隐私保护,用户可以决定是否给予用户剪贴板的调用权限,系统还可以通过本地算法智能识别剪切板访问,降低用户打扰。此前,iOS 14率先推出了模糊定位功能,但是其范围限定在通讯基站范围,应用通过交叉基站同样可以确定用户位置。小米运用边缘计算和大数据支撑融合模糊定位服务,推出了全球首个基于差分隐私的融合模糊定位,模糊范围可以随意调节。最后,小米还开发了安卓系统首个默认开启的隐私隔离沙盒,将敏感隐私信息独立隔离,用户可以有效保护照片和社交信息。

正是这些创新,使得MIUI成为了全球首家获得德国莱茵TÜV《安卓系统增强隐私保护测试》的手机操作系统。2020年6月,小米安全与隐私委员会还通过宣传月活动,提升全员的安全隐私保护意识,让小米的软硬件产品都能够高标准保护用户信息安全,进而唤醒互联网行业以及网民对信息安全和隐私的保护意识。

百万美金大奖

是成果展示,也是投入的决心

过去一年,小米拿出了一系列令人信服的技术成绩单,比如DXO相机霸榜121天、小米无人智能工厂正式投产、快充/无线快充始终领跑全球、小米一指连技术发布、率先发布第三代屏下摄像头技术等等,在全球业界和消费者群体中都引发了巨大的反响。

今天,我们第二次颁发百万美金大奖,前后已有三个技术团队获此殊荣。事实上,在最高领奖台背后,还有许多团队也拿出了非常优秀的技术成果。百万美金大奖的初衷,就是要让小米的工程师不仅仅是幕后英雄,还要成为最耀眼的明星。

小米十周年的时候,我们提出了“技术为本、性价比为纲、做最酷的产品”这永不更改的三大铁律。技术为本是三大铁律的第一条。我们具体要如何做呢?我觉得最重要的是做好三件事。

第一,始终坚持加强研发投入。2020年小米研发投入全年近100亿元,在全中国公司中进入了前20名。

第二,始终坚持重视人才队伍的建设。没有顶尖人才,创新就是无本之木,无源之水。2021年,小米将扩招5000名工程师,占小米目前员工总数超20%。我们相机部在全球设立了9个研发中心,其中5个是国际研发中心。总之,哪里有人才,小米就到哪里去。

第三,始终坚持营造鼓励创新、鼓励钻研的工程师文化氛围。我们今天的成功,归根结底都源于小米内部浓郁的工程师文化。工程师就是小米最重要的资产。我们设置的小米技术奖,是小米今天内部分量最重的荣誉和奖项,就是要充分突出这一点。只要你热爱技术,只要你技术过硬,在小米你一定能够实现自己的技术梦想。

百万美金大奖体现的正是我们要坚持做好这三件事的决心。让我特别激动和欣慰的是,我还发现,今天我们获得百万美金大奖的两支技术团队都非常年轻,小米就是要给优秀的年轻人机会,让更多的年轻的技术人才持续不断地涌现出来。这才是小米赢得当下,更赢得未来的最大底气。

我也希望,小米全体研发团队,今年继续加油,拿出更多让全世界惊叹的技术成果。明年初在这里,能有更多代表全球顶尖水准的团队能在这里领走更多大奖!

在小米,我们尊重每一个疯狂的想法,我们赞赏探索技术无人区的勇气,我们包容成功道路上的大胆试错。我相信只有这样,才能用创新之火照亮小米的未来,飞向全球米粉心目中的星辰大海!

程序员必收藏的六个网站

thbcm阅读(206)

GitHub

作为开源代码库以及版本控制系统,Github拥有超过900万开发者用户。随着越来越多的应用程序转移到了云上,Github已经成为了管理软件开发以及发现已有代码的首选方法。

Gitee【码云】

Gitee.com 是 OSCHINA.NET 推出的代码托管平台,支持 Git 和 SVN,提供免费的私有仓库托管。目前已有超过 500 万的开发者选择 Gitee。

CSDN

中国专业IT社区CSDN(Chinese Software Developer Network) 创立于1999年,致力于为中国软件开发者提供知识传播、在线学习、职业发展等全生命周期服务。

12580code

12580code中外精品源码集聚站,拥有APP/Web/游戏/应用程序等精品源码,给开发者提供优质的代码分享平台。

博客园

博客园是一个面向开发者的知识分享社区。自创建以来,博客园一直致力并专注于为开发者打造一个纯净的技术交流社区,推动并帮助开发者通过互联网分享知识,从而让更多开发者从中受益。

w3cschool

W3Cschool是一个专业的编程入门学习及技术文档查询网站,提供包括HTMLCSSJavascriptjQueryCPHPJavaPythonSqlMysql等编程语言和开源技术的在线教程及使用手册,是类似国外w3schools的学习社区及菜鸟编程平台。

浅谈JavaScript编程语言的编码规范

thbcm阅读(169)

对于熟悉 C/C++ 或 Java 语言的工程师来说,JavaScript 显得灵活,简单易懂,对代码的格式的要求也相对松散。很容易学习,并运用到自己的代码中。也正因为这样,JavaScript 的编码规范也往往被轻视,开发过程中修修补补,最终也就演变成为后续维护人员的恶梦。软件存在的长期价值直接与编码的质量成比例。编码规范能帮助我们降低编程中不必要的麻烦。而 JavaScript 代码是直接发送给客户浏览器的,直接与客户见面,编码的质量更应该受到关注。

本文浅谈 JavaScript 编程中关于编码规范的问题,分析其中缘由。希望引起更多 Web 开发人员对 JavaScript 编码规范问题的关注和对软件产品质量问题的重视。

前言

提及 C/C++ 和 Java 编码规范,相信许多工程师并不生疏。但说到 JavaScript 语言的编码规范,也许您会忍俊不禁。JavaScript 不是语法很灵活吗?变量随时用随时可以声明;语句结束符可以不要;字符串和数字也可以相加;参数多一个少一个也不会报错。没错,当您从 C/C++ 和 Java 严格的语法规定之下,转向 JavaScript 语言,会觉得自由了很多,轻松了很多。语法松散是 JavaScript 重要的特征。它灵活易懂,给开发人员带来了很多方便,但如果编写过程中不注意,代码的调试成本和维护成本则会无形地增加。

JavaScript 编码会随应被直接发送到客户端的浏览器,代码规范不只是代码质量的保证,也影响到产品的长期信誉。希望 JavaScript 编程语言的规范问题也能同样引起更多朋友的关注。

JavaScript 编码规范建议

本文就 JavaScript 编码过程中涉及的排版、命名、声明、作用域、及一些特殊符号的使用等方面,根据个人在学习工作中的总结,给出自己的一些建议,并分析其中缘由,以供参考。

JavaScript 文件引用

JavaScript 程序应该尽量放在 .js 的文件中,需要调用的时候在 HTML 中以 <script src=”filename.js”> 的形式包含进来。JavaScript 代码若不是该 HTML 文件所专用的,则应尽量避免在 HTML 文件中直接编写 JavaScript 代码。因为这样会大大增加 HTML 文件的大小,无益于代码的压缩和缓存的使用。

另外,<script src=”filename.js”> 标签应尽量放在文件的后面。这样会降低因加载 JavaScript 代码而影响页面中其它组件的加载时间。

代码排版

行长度

每行代码应小于 80 个字符。如果代码较长,应尽量选择换行,下一行代码应缩进 8 个空格。这样可以使代码排版整齐,减轻阅读代码的疲劳感。换行缩进 8 个空格可以和代码段的缩进 4 个空格区分开,以增强代码的可阅读性。

行结束

JavaScript 语句应该以分号结束。但大多数浏览器允许不写分号,只要在本应是分号的地方有一个换行符就行。但是如果代码行较长需要换行的时候,有哪些注意事项呢?换行应选择在操作符和标点符号之后,最好是在逗号’,’之后,而不要在变量名、字符串、数字、或’)’ ‘]’ ‘++’ ‘–‘等符号之后换行。

这样可以有效的防止拷贝、粘贴而引起的错误,并可有效地增强代码的可阅读性。代码的输出符合我们的期望。但就写法而言,对 valueB 的赋值语句是在变量 valueA 之后进行的换行,这很容易被误解为 valueB=ValueA,给阅读造成障碍。而对 valueC 的复制语句是在’+’之后进行的换行,就容易理解的多。这也是本文所提倡的换行方式。

造一个抖音 App

thbcm阅读(235)

抖音短视频 App 火速爆红,没几年就成为了国民级 App。低成本的体验方式,不管是大爷大妈,还是刚会玩手机的小孩儿,都沉迷之中无法自拔。

今天小编给大家推荐两个 GitHub 项目,都是移动端开发者开发的复制版抖音 App,分别对应着 iOS 系统和 Android 系统。

iOS 仿抖音 App

这个抖音 Demo 适配 iPhone、iPad,同时兼容 iOS 8.0 – iOS 12.0系统。采用 Object-C 语言编写。标星 1.5K Star,项目地址:

https://github.com/sshiqiao/douyin-ios-objectc

本项目共分为三个部分:抖音个人主页实现、网络视频相关功能实现、WebSocket 实现 IM 即时聊天功能。

Demo 预览

此外,作者还提供了开发手册,每个模块开发过程记录了下来。作者同样用到了 Charles 神器抓包,老逛以前发布的文章就派上用场了,结合文章 抓包神器:Charles 食用更佳。

仿抖音 App 开发手册

Android 仿抖音 App

这个 Demo 涉及的技术要点如下:

  • Recycler + PagerSnapHelper 实现全屏切换播放效果,

  • 使用 Lottie 库加载 Json 动画

  • BottomSheetDialogFragment 实现分享评论弹框功能

  • CoordinatorLayout + AppBarLayout 实现折叠布局。

该项目标星 1K Star,项目地址:

https://github.com/18380438200/Tiktok

Demo 预览

最后温馨提醒:

刷抖音时能带给你短暂的愉悦感,但如果长期沉迷于刷抖音,甚至会熬夜刷抖音,晚睡晚起,会使自己碎片化时间无法被利用,心情浮躁,专注力下降。你可以网络段子张口就来,明星网红关注比谁都多,但是个人认知水平并没有提高,我说的是不是你?沉下心来学习专业技能,才是我们最应该做的。

推荐好课

1. iOS 开发手册

2. Android 教程

3. Android SDK 上手指南

CSS教程:可读性可维护性良好的CSS文件

thbcm阅读(202)

在大多数文章中,我们并未特别注意 CSS 文件的可维护与可读性的问题,当完成一项前端的工作之后,许多人都会忘记该项目的结构与细节。然而代码并不是马上就能完全定型,在余下的时间里还有不断的维护工作,而这些工作也许不会是你自己完成。所以,结构优良的代码能很大程度上优化它的可维护性。下面列出四则技巧提高 CSS 文件可维护性的方法,以此作为指南,以一种较好的 CSS 样式组织习惯来进行 WEB 前端开发。 

一、CSS 样式文件分解

对于小项目,在写代码之前,按页面结构或页面内容将代码分为几块并给予注释。例如,可以分别将 全局样式、布局、字体样式、表单、评论和其他分为几个不同的块来继续工作。

而对于较大的工程,这样显然不会有什么效果。此时,就需要将样式分解到几个不同的样式表文件。下面的master stylesheet 就是这一方法的例子,它的工作主要是导入其他样式文件。使用这一方法不仅能优化样式结构,而且有利于减少一些不必要的服务器请求。而分解文件的方法就有许多种,master stylesheet 使用了最常见的一种。

@import "reset.css";
@import "layout.css";
@import "colors.css";
@import "typography.css";
@import "flash.css";
/* @import "debugging.css"; */

同时对于大型项目,你也可以加上 CSS 文件的升级标志或者一些诊断等其他措施,这里不再详述。大家注意在实现工作中总结与思考。

二、为 CSS 文件建立索引

为了能够迅速的了解整个 CSS 文件的结构,在文件开头建立文件索引是一个不错的选择。

一种可行的方法是建立树形的索引,结构上的 id 和 class 都可以成为该树的一个分支。


[Layout]

* body

+ Header / #header

+ Content / #content

– Left column / #leftcolumn

– Right column / #rightcolumn

– Sidebar / #sidebar

– RSS / #rss

– Search / #search

– Boxes / .box

– Sideblog / #sideblog

+ Footer / #footer

Navigation #navbar

Advertisements .ads

Content header h2

或者也可以这样:

[Contents]

1. Body

2. Header / #header

2.1. Navigation / #navbar

3. Content / #content

3.1. Left column / #leftcolumn

3.2. Right column / #rightcolumn

3.3. Sidebar / #sidebar

3.3.1. RSS / #rss

3.3.2. Search / #search

3.3.3. Boxes / .box

3.3.4. Sideblog / #sideblog

3.3.5. Advertisements / .ads

4. Footer / #footer

另一种方式可以只是先简单的将内容列举出来,也不需要缩进。下面的一个例子中,如果你需要跳至 RSS 部分你只需要简单的搜索。

[Contents]

1. Body

2. Header / #header

3. Navigation / #navbar

4. Content / #content

5. Left column / #leftcolumn

6. Right column / #rightcolumn

7. Sidebar / #sidebar

8. RSS / #rss

9. Search / #search

10. Boxes / .box

11. Sideblog / #sideblog

12. Advertisements / .ads

13. Footer / #footer

/*–[8. RSS / #rss]–*/

#rss { … }

#rss img { … }

定义这样一个样式检索可以很有效的使其他人阅读学习你的代码变得容易。在制作大项目的时候,你也可以将检索打印出来从而在你阅读代码的时候方便查阅。您还可以参考下面的文章。

三、格式化CSS属性

当我们编写代码的时候,使用一些特殊的编码风格会对提高 CSS 代码的可读性有很大帮助。许多人都有各自不同的编码风格。一部分人习惯于将颜色和字体的代码放在前面,另外一部分则更喜欢将类似浮动和定位的更“重要”的属性放在前面。类似的,也可以将页面元素按照它在布局中的结构进行排序:

body,

h1, h2, h3,

p, ul, li,

form {

margin: 0;

padding: 0;

border: 0;

}

一些开发者用一种更为有意思的方法:他们将属性按首字母的顺序排列。值得注意的是,这样一种方法可能对某些浏览器会产生问题。不管自己的格式如何,你要确保你已经清晰的定义了这些格式方法。这样,你的同事在阅读你的代码的时候将会感谢你的努力。您还可以参考下面的文章。

四、合理的利用缩进

为了让你的代码给人感觉更为直观,你可以使用一行来定义大纲元素的样式。当指定的选择器里的属性超过三个的时候,这种方式将带来混乱。但是,适度的使用这种方式,你可以很清楚的区分相同类的不同点。

#main-column { display: inline; float: left; width: 300px; }

#main-column h1 { margin-bottom: 20px; }

#main-column p { color: #333; }

同时,样式修改的维护也是个比较麻烦的问题。很多人修改样式之后就忘记了,结果后来又发现修改的样式导致了页面出错,不得不苦苦寻找。因此,为修改的样式构建一个特殊的格式就很必要了。一种很简单的方式是,给修改过的样式缩进,同时,也可以使用一些注释(比如”@new”)来做一个标识。

#sidebar ul li a {

display: block;

background-color: #ccc;

border-bottom: 1px solid #999; /* @new */

margin: 3px 0 3px 0;

padding: 3px; /* @new */

}

总的来说,只有建立一个合适的样式指南才会对样式表的可读性有所帮助。记住,移去每一个对你理解文件没有帮助的样式指南,避免对过多的元素使用过多的样式指南。然后,为了一个可读性可维护性良好的 CSS 文件而努力吧。

CDH环境搭建及部署

thbcm阅读(223)

一、概述

Cloudera版本(Cloudera’s Distribution Including Apache Hadoop,简称“CDH”),基于Web的用户界面,支持大多数Hadoop组件,包括HDFS、MapReduce、Hive、Pig、 Hbase、Zookeeper、Sqoop。

二、安装部署

2.1 集群架构

序号 IP地址 主机名 系统版本
1 10.211.55.100 zero Centos 7.7
2 10.211.55.101 Hadoop1 Centos 7.7
3 10.211.55.102 Hadoop2 Centos 7.7

2.2 基础环境配置

2.2.1 网络配置
vi /etc/sysconfig/network-scripts/ifcfg-eth0

BOOTPROTO=static 
ONBOOT=yes
IPADDR=10.211.55.100
NETMASK=255.255.255.0 
GATEWAY=10.211.55.1
systemctl restart network.service  #重启网络服务
2.2.2 禁用防火墙和SELINUX
systemctl stop firewalld
systemctl disable firewalld
vi /etc/sysconfig/selinux

SELINUX=disabled  #将SELINUX的值改为disabled

reboot  #重启设备使selinux的配置生效
2.2.3 更改主机名
hostnamectl set-hostname  zero
2.2.3 修改hosts
vi /etc/hosts

10.211.55.100 zero
10.211.55.101 hadoop1
10.211.55.102 hadoop2

reboot  #修改完后重启生效
2.2.4 同步时间
yum -y install ntp  #安装NPT服务
vi /etc/ntp.conf  #修改配置文件

#注释掉原有的server指向
#server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst

#zero节点指向
server 0.cn.pool.ntp.org
server 0.asia.pool.ntp.org
server 3.asia.pool.ntp.org

server 10.211.55.100 iburst  #Hadoop1/Hadoop2节点指向zero节点
ntpdate -u cn.pool.ntp.org  #同步网络时间

#重启ntp服务
systemctl start ntpd
systemctl enable ntpd

hwclock --localtime -w  #将系统时间写入本地硬件时钟时间
2.2.5 配置SSH免密登录
ssh-keygen -t rsa  #不输入密码,一路回车

ssh-copy-id hadoop1
ssh-copy-id hadoop2

#测试连通性
ssh 'zero'
ssh 'hadoop1'
ssh 'hadoop2'
2.2.6 安装JDK
mkdir /usr/Java/  #创建目录
tar -zxvf jdk1.8.0_211.tar.gz -C /usr/Java/  #解压JDK包到指定目录
vi /etc/profile	 #配置环境变量

#JAVA
export JAVA_HOME=/usr/Java/jdk1.8.0_211
export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib export PATH=${JAVA_HOME}/bin:$PATH
source /etc/profile  #使配置文件生效
java -version  #查看版本信息 检测安装是否成功

#安装成功后的返回信息
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
2.2.7 安装MySQL(主节点安装即可)
#查看系统中是否已安装MySQL服务 如果存在则删除MySQL及其依赖的包
rpm -qa | grep mysql
yum list installed | grep mysql
wget http://repo.mysql.com/mysql57-community-release-el7-8.noarch.rpm
rpm -ivh mysql57-community-release-el7-8.noarch.rpm
yum install mysql-server #安装MySQL 如出现提示 一路y到底

安装完毕后,运行MySQL,后在 /var/log/mysqld.log文件中会自动生成一个随机密码。

service mysqld start  #运行MySQL
grep "password" /var/log/mysqld.log  #取得随机密码 用于登录 MySQL 服务端

#返回信息如下 “6WjiI.UxuoaF”即为MySQL登陆密码
2021-01-05T11:04:28.684402Z 1 [Note] A temporary password is generated for root@localhost: 6WjiI.UxuoaF

登录到 MySQL 服务端并更改密码。

/*修改密码*/
SET PASSWORD = PASSWORD('new password');
ALTER USER 'root'@'localhost' PASSWORD EXPIRE NEVER;
flush privileges;

/*设置用户 root 可以在任意 IP 下被访问*/
grant all privileges on *.* to root@"%" identified by "new password";

/*设置用户 root 可以在本地被访问*/
grant all privileges on *.* to root@"localhost" identified by "new password";

/*刷新权限使其生效*/
flush privileges;

2.3 Cloudera Manager的安装及部署

2.3.1 安装Cloudera Manager
yum -y install chkconfig python bind-utils psmisc libxslt zlib sqlite cyrus-sasl-plain cyrus-sasl-gssapi fuse portmap fuse-libs redhat-lsb  #安装第三方依赖包
mkdir -p /opt/cloudera-manager #创建目录

解压Cloudera Manager包到/opt/cloudera-manager目录下。

tar -zvxf cloudera-manager-centos7-cm5.14.0_x86_64.tar.gz  -C  /opt/cloudera-manager/
2.3.2 配置Cloudera Manager

修改agent配置文件。

vi /opt/cloudera-manager/cm-5.14.0/etc/cloudera-scm-agent/config.ini

#配置文件修改如下

# Hostname of the CM server.
server_host=zero

# Port that the CM server is listening on.
server_port=7182

为CM创建一个专用的普通用户 cloudera-scm。

useradd --system  #表示创建的是系统用户
--home=/opt/cloudera-manager/cm-5.14.0/run/cloudera-scm-server  #指定了用户的主目录
--no-create-home #表示不再创建用户的主目录
--shell=/bin/false  #不作为登陆用户 
--comment "Cloudera SCM User" 
cloudera-scm  #用户名

配置数据库访问权限,添加用户。

grant all privileges on  *.*  to 'temp'@'%' identified by 'password' with grant option;
flush privileges;

在主节点上执行CM在MySQL中的初始化脚本。

mv mysql-connector-java.jar /usr/share/java/mysql-connector-java.jar

#进入初始化脚本目录下
cd /opt/cloudera-manager/cm-5.14.0/share/cmf/schema

#运行初始化脚步
./scm_prepare_database.sh mysql -h zero -utemp -ppassword --scm-host zero scm scm scm

配置CDH源(注意下载的时候需要版本对应,el5/6/7分别对应CentOS5/6/7。)

#创建目录
mkdir -p /opt/cloudera/parcel-repo  #主节点
mkdir -p /opt/cloudera/parcels  #所有节点

#将parcel文件移动到parcel-repo目录下
mv CDH-5.14.0-1.cdh5.14.0.p0.24-el7.parcel  /opt/cloudera/parcel-repo/

#将json文件移动到parcel-repo目录下
mv manifest.json  /opt/cloudera/parcel-repo/

#重命名校验码文件并移动到parcel-repo目录下
mv CDH-5.14.0-1.cdh5.14.0.p0.24-el7.parcel.sha1  /opt/cloudera/parcel-repo/CDH-5.14.0-1.cdh5.14.0.p0.24-el7.parcel.sha

更改目录所有人

chown -R cloudera-scm:cloudera-scm /opt/cloudera/parcel-repo/  #主节点
chown -R cloudera-scm:cloudera-scm /opt/cloudera/parcels/  #所有节点
2.3.3 启动CM进程服务

启动server(主节点)

/opt/cloudera-manager/cm-5.14.0/etc/init.d/cloudera-scm-server start
Starting cloudera-scm-server:                              [  确定  ]  #成功启动后的返回信息

启动agent(所有节点)

/opt/cloudera-manager/cm-5.14.0/etc/init.d/cloudera-scm-agent start
Starting cloudera-scm-agent:                               [  确定  ]  #成功启动后的返回信息
2.3.3 开始部署

打开http://10.211.55.100:7180/进入CM初始界面,账号密码为admin

登陆进入勾选同意条款,点击继续,选择免费版本。

继续下一步,勾选安装主机。

群集安装默认勾选即可,点击继续,等待安装完成。

点击继续,检查主机正确性,参照给出的信息进行修复。

点击继续,选择需要的服务。

点击继续,进行角色分配。

配置数据库,使其连接成功。

审核更改页面直接默认,点击继续。

等待部署完成。

点击继续,安装完成。

三、错误&解决

#错误
Your password does not satisfy the current policy requirements

#解决方法
vi /etc/my.cnf  #修改配置文件my.cnf
validate_password=off  #关闭密码策略设置validate_password
service mysqld restart  #重启服务
#错误
为CDH群集安装指定主机无法勾选。

#解决方法
/opt/cloudera-manager/cm-5.14.0/etc/init.d/cloudera-scm-server stop  #停止server
/opt/cloudera-manager/cm-5.14.0/etc/init.d/cloudera-scm-agent stop  #停止agent

#删除/opt/cloudera-manager/cm-5.14.0/lib/cloudera-scm-server-db/data/目录下内容
rm -rf /opt/cloudera-manager/cm-5.14.0/lib/cloudera-scm-server-db/data/*
/*删除MySQL数据库中scm数据库下的hosts表中的数据*/
use scm;
delete from HOSTS;
#错误
MainThread agent ERROR Error, CM server guid updated, expected 7cda865f-a833-40d1-9fa6-761631c74326, received e2678b78-7c5e-4703-91b6-c52e2875988c

#解决方法
rm -rf /opt/cloudera-manager/cm-5.14.0/lib/cloudera-scm-agent/cm_guid
#错误
ERROR Table 'scm.CM_VERSION' doesn't exist

#解决方法
vi /etc/my.cnf  #修改配置文件my.cnf
lower_case_table_names = 1  #[mysqld]节点下添加
service mysqld restart  #重启服务
#错误
ERROR WebServerImpl:com.cloudera.server.web.cmf.search.components.SearchRepositoryManager: The server storage directory [/var/lib/cloudera-scm-server] doesn't exist.

#解决方法
mkdir /var/lib/cloudera-scm-server
chown -R cloudera-scm:cloudera-scm /var/lib/cloudera-scm-server    #创建目录并加上权限


推荐好课:

从0基础到前端开发就业

PHP快速入门到开发就业

PHP学习路线图 最全PHP自学指南

thbcm阅读(223)

对于广大零基础的PHP自学者,往往不知道如何系统的学习PHP,导致平白浪费了很多时间。本文将为大家带来最详细的php学习路线图,同时还会附上相应的权威教程,让广大PHP自学者少走许多弯路。推荐课程:PHP快速入门到开发就业

PHP学习路线图

点击查看清晰大图

第一阶段:网页入门


学习目标:

可满足企业基本的建站要求,可自由仿制任何网站页面,并解决浏览器兼容性、PC端与移动端兼容性问题。能够使用Javascript验证技术,无压力的胜任前端工程师职位。


知识点:

1)Html(掌握)

html文本排版、表格和超级链接、表单和框架


2)CSS

css语法与属性、盒子模型、DIV+CSS布局


3)Html5+Css3(掌握)

html5、css3


4)Bootstrap(重点)

Bootstrap的布署、全局CSS样式、CSS组件


5)Javascript(重点)

JS简介、JS语法、JS引入方式、JS内置对象、BOM模型、DOM模型、事件编程


6)Jquery(重点)

jquery各种选择器、DOM与jquery对象、属性操作、jquery特效、事件操作、文档处理、jquery插件机制


第二阶段:PHP入门


学习目标:

通过该阶段学习,能够掌握使用面向过程的编程方式,解决一些常规业务的逻辑,实现表单传值、文件编程、会话技术、图像处理等事项。让自己完全具备建设初级动态的能力。


知识点:

1)PHP环境搭建(掌握)

静态与动态网站的区别、WEB程序的访问流程、搭建基于域名的虚拟主机、自定义环境搭建、搭建wamp环境、环境体验-安装discuz论坛


2)PHP核心(重点)

变量和常量、数据类型和运算符、流程控制、函数、文件包含、运算符、字符串、数组


3)Mysql基础(重点)

SQL操作、列类型与列属性、字符集、表关系、mysql三大查询、高级数据操作、数据的备份与还原、mysql用户权限管理、PHP操作Mysql


4)PHP典型技术(重点)

http协议、表单传值、文件处理、会话技术、GD图像处理


5)项目实战(掌握)

bbs论坛后端实现

第三阶段:PHP中级


学习目标

在这个阶段,要学会利用OOP思想和MVC设计,实现手写PHP项目框架能力。拥有实现动态网站主流功能的能力,如无限极分类、页面数据检索、内容采集等。能掌握实现页面静态化和邮件处理等较高级的技术。具备建设主流中小型网站的能力。

知识点:

1)PHP面向对象(掌握)

面向对象基础、使用面向对象、面向对象三大特性、PHP中的继承、对象的遍历、对象序列化、反射机制、命名空间


2)PDO(熟悉)

PDO基本操作及增删改查、PDO属性控制、PDO预处理、PDO异常处理、PDO封装                     


3)ICFrarme框架(重点)

MVC设计模式、框架搭建


4)Smarty模版(熟悉)

模版技术原理、Smarty快速入门、Smarty模版设计、Smarty程序设计、Smarty缓存技术


5)项目升级(重点)

邮件技术、页面静态化、正则表达式、内容采集、功能完善

第四阶段:PHP高级


学习目标:

能够使用ThinkPHP框架进行项目的快速开发。可以实现后台的RBAC权限管理功能,掌握代码管理、前后台交互、多表连接、数据分析、轮询技术、网站优化技术。通过该阶段学习后,将拥有中大型网站及办公室OA系统的开发能力。

知识点:


1)SVN(掌握)

SVN概述及安装、SVN使用详解、配置多仓库与权限控制、SVN服务器配置与管理、钩子程序


2)XML(熟悉)   

XML语法、SimpleXML,XPath、案例-在线词典      


3)Ajax(掌握)  

Ajax快速入门、Ajax对象、发送get、post请求、用XML、JSON传输数据、Ajax跨域请求、Ajax案例-分页,聊天室


4)ThinkPHP(重点)

ThinkPHP快速入门、ThinkPHP控制器、ThinkPHP视图、ThinkPHP模型、ThinkPHP实用项


5)Linux(重点)  

linux安装、shell使用、VI编辑器、用户、组、文件管理、Lamp环境搭建   


6)优化技术(重点)

数据库优化、Sphinx全文索引、Memcache、URL优化

第五阶段:PHP企业级开发


学习目标:

使用ThinkPHP框架实现真实商城主流业务逻辑(例如属性筛选商品、商品查找、购物车等),并实现商城常用的QQ登录、支付、接口开发等功能。并掌握商城服务器架构高级知识如集群、负载均衡、分布式!

在该阶段学习后,将掌握大型主流商城开发,同时拥有对门户网站、商城系统、办公系统等项目可以进行系统性能调优的能力。


知识点:

1)Redis(掌握)   

Nosql常见产品介绍、安装启动、数据类型讲解、PHP支持redis、安全认证与高级案例、持久化机制、主从配置


2)九大接口编程(重点)

支付、配送、微信、短信、邮件、地图、百度API、腾讯API、本地数据接口


3)MongoDB(重点)

MongoDB认识、基本和常用命令、索引与用户管理、数据导出与备份、主从复制与分片、PHP支持MongoDB


4)Mysql读写分离(重点)    

原理、log-bin讲解、配置步骤、代码实现读写分离、ThinkPHP中使用读写分离     


5)服务器架构(重点)

WEB服务器集群、Nginx负载均衡、Session共享、反向代理服务器

第六阶段:PHP拓展


学习目标:

1、掌握PHP开源产品的使用,并能进行快速、深度的二次开发。学完后能掌握各种企业门户网站、政府机关、教育机构、媒体机构、个人站长等网站的快速开发。

2、掌握混合式开发方法开发手机APP,该APP可兼容安卓手机和IOS手机,学完后可实现PC端网站(或企业OA平台)内容在手机端同步观看和更新!


知识点:

1)WebApp(重点)        

框架基础、PhoneGap底层实现、Hyrid混合式开发、应用JS SDK类库


2)CMS深度开发(重点)

理解cms系统、熟练应用dedecms系统标签、利用dedecms开发电影网、应用dedecms的数据采集     


3)Hadoop(了解)   

Hadoop安装与配置、HDFS配置、Hadoop入门案例、PHP编写MapReduce   


4)Mysql高级(重点)

外键和范式、视图和事务安全、触发器、函数、存储过程、索引


5)Js高级(重点)

js常用事件、js面向对象、js闭包、js函数调用

使用jQuery,CSS,JSON和ASP.NET创建新闻轮换控件

thbcm阅读(187)

这个新闻轮换控件能在网页上的同一个地方显示几条新闻。新闻被拆开几页,为了放置在一个指定的区域。每一页也能包含一对新闻列表。 通过点击底部的页码,能够在不同的页面之间导航,点击页的每个新闻项,就能查看新闻的详细信息。新闻能像幻灯片一样去查看。它提供自动切换下一个(幻灯片)功能,以及过渡的样式。

使用 JQuery 为了:

    1、对 web server 进行 JQuery Ajax Request 请求,得到 JSON 格式新闻    2、绑定数据(JSON 格式的新闻)到 HTML 控件    3、在数据 binding 之后设置控件的样式    4、新闻之间的导航    5、用户交互    6、改变和设置样式    7、实现 javascript 的效果新闻滚动控件使用 ASP.NET 从新闻存储(例如数据库,xml文件,rss,…)汇集新闻。将它转化成指定类型(NewsItem)。 然后将 newsItem 对象的集合转化成 JSON 格式的数据,作为新闻的数据来源发送到客户端。

这个控件使用开源的 Json.NET 类库,它使 JSON 格式的数据在 .NET 中使用更加的方便。这个类库的关键的功能包括一个灵活的 JSON 序列化,能快速的将 .net 类转换成 JSON ,将 JSON 转换成 .net 类。了解更多的 Json.NET 类库(代码。示例,和文档),点击这里。

新闻滚动控件主要使用 jQuery Image Rotator sample 的思想。  通过 Soh Tanaka 的描述,你能找到更多的关于如何去构造一个滚动的图片效果。

这个新闻滚动控件使用 jQuery Cycle 插件来旋转新闻插件,它是一个轻量级的幻灯片插件,在页面上,这个插件为开发者提供强大的旋转能力来轮转不同类型的 HTML 控件。了解更多的 jQuery Cycle 插件,点击这里。
你需要使用该控件:
1、引用必要的资源到你的 HTML 页面(.aspx 页面):

<%@ Register Src="~/TopNews.ascx" TagName="TopNews" TagPrefix="ctrl" %>

<body>

<form id="form1" runat="server">

<div>

<ctrl:TopNews runat="server" id="TopNews1" />

</div>

</form>

</body>

2、在你的 .aspx 页面中注册和嵌入 TopNews.ascx 控件。

<%@ Register Src="~/TopNews.ascx" TagName="TopNews" TagPrefix="ctrl" %>

<body>

<form id="form1" runat="server">

<div>

<ctrl:TopNews runat="server" id="TopNews1" />

</div>

</form>

</body>

3、 一开始控件通过调用  DOM 尾部的 JavaScript 的 TopNews() 函数。 这个函数向服务端发送一个 Ajax 请求。得到 JSON 格式的新闻。然后将新闻绑定到控件上面。 在绑定之后,设置控件的样式,接着滚动新闻。

<script type="text/javascript">

new TopNews('#Container', 7,true,6000);

</script>

TopNews function parameters:

parameter 1(objRoot): newsRotator control container (a jquery selector),

the control uses this parameter as a prefix (root object) of every

jquery selector inside the control.this prefix helps to have multiple instance

of control in the page without any worry of jquery selection conflict.

parameter 2(newsCountPerPage): number of news items in a page.

parameter 3(viewSubtitle): a boolean value makes subtitle section

of the control enable or disable. the rest of the news titles shows

in the subtitle section randomly at the bottom of the current page.

parameter 4(Interval): news rotation (slideshow) interval in millisecond.

4、需要一个服务端来收集新闻。 然后将新闻转化成 JSON 格式,将它发送到客户端。 

在客户端,我们使用 Jquery 发送一个 Ajax 请求去调用服务端的方法。

//call ASP.NET page method asynchronous (send and recives data in JSON format)

PageMethod: function(fn, paramArray, successFn, errorFn) {

var pagePath = window.location.pathname;

var that = this;

//Call the page method

$.ajax({

type: "POST",

url: pagePath + "?Callback=" + fn,

contentType: "application/json; charset=utf-8",

data: paramArray,

dataType: "json",

//that is a reference to the object calling this callback method

success: function(res) { successFn(res, that) },

error: errorFn

});

}

在服务器端,我们像下面这样去实现:

protected void Page_Load(object sender, EventArgs e)

{

// *** Route to the Page level callback 'handler'

this.HandleCallbacks();

}

// Callback routing

public void HandleCallbacks()

{

if (string.IsNullOrEmpty(Request.Params["Callback"]))

return;

// *** We have an action try and match it to a handler

switch (Request.Params["Callback"])

{

case "fetchAllNews":

this.FetchAllNews();

break;

}

Response.StatusCode = 500;

Response.Write("Invalid Callback Method");

Response.End();

}

public void FetchAllNews()

{

List<NewsItem> lsttst = new List<NewsItem>();

lsttst.Add(new NewsItem("Environment of Australia",

this.ResolveUrl("~/img/news1.jpg"),

this.ResolveUrl("~/img/news1_thumb.jpg"),

"Australia has a rich variety of endemic legume

species that thrive in nutrient-poor soils because

of their symbiosis with rhizobia bacteria and mycorrhizal fungi",

DateTime.Now.ToShortDateString()));

lsttst.Add(new NewsItem("Economy of Australia",

this.ResolveUrl("~/img/news2.jpg"),

this.ResolveUrl("~/img/news2_thumb.jpg"),

"The Australian dollar is the currency of the

Commonwealth of Australia, including Christmas Island,

Cocos (Keeling) Islands, and Norfolk Island",

DateTime.Now.ToShortDateString()));

lsttst.Add(new NewsItem("Demographics of Australia and

Immigration to Australia", this.ResolveUrl("~/img/news3.jpg"),

this.ResolveUrl("~/img/news3_thumb.jpg"),

"Most of the estimated 21.8 million Australians are

descended from colonial-era settlers and post-Federation

immigrants from Europe", DateTime.Now.ToShortDateString()));

lsttst.Add(new NewsItem("Religion in Australia",

this.ResolveUrl("~/img/news4.jpg"),

this.ResolveUrl("~/img/news4_thumb.jpg"),

"Australia has no state religion. In the 2006 census,

64% of Australians were listed as Christian of

any denomination, including 26% as Roman Catholic and

19% as Anglican", DateTime.Now.ToShortDateString()));

lsttst.Add(new NewsItem("Education in Australia",

this.ResolveUrl("~/img/news5.jpg"),

this.ResolveUrl("~/img/news5_thumb.jpg"),

"School attendance is compulsory throughout Australia.

In most Australian States at 5–6 years of age all children

receive 11 years of compulsory education",

DateTime.Now.ToShortDateString()));

Response.ContentType = "application/json; charset=utf-8";

Response.Write(JavaScriptConvert.SerializeObject(lsttst));

Response.End();

}

联系我们