热门总结

  • Hyperapp 155 0 1 发布
    简介

    Hyperapp是一个用于开发Web应用程序前端(主要是View部分)的现代JavaScript库,它的大小仅有1.3kB,并且非常容易上手。

    Hyperapp的架构借鉴了React、Redux以及Elm,支持JSX同时也提供了一些JSX的替代方案,比如h函数(Hyperapp的首字母)、hyperapp/html、hyperx、t7。

    Hyperapp的初衷就是以尽量少的代码做尽量多的事。但Hyperapp虽小,仍然包含了状态管理、虚拟DOM引擎,所有这些都是独立实现,不依赖于任何第三方库的。

    导入使用CDN不指定版本 <script src="https://unpkg.com/hyperapp"></script> 指定版本 <script src="https://unpkg.com/hyperapp@1.0.1"></script> HelloWord

    Hyperapp可以使用JSX表示法,以及基于ES6字符串模板的Hyperx表示法。下面两种写法的代码都准备好了,您可以根据自己的喜好自由选用。

    使用JSX<body> <script src="https://unpkg.com/hyperapp@1.0.1"></script> <script src="https://unpkg.com/babel-standalone"></script> <script type="text/babel"> const { h, app } = hyperapp /** @jsx h */ const state = { greeting: "Hello,world" } const actions = {} const view = state => <h1 id="title">{state.greeting}</h1> app(state, actions, view, document.body) </script> </body> 使用Hyperx<body> <script src="https://unpkg.com/hyperapp@1.0.1"></script> <script src="https://wzrd.in/standalone/hyperx"></script> <script> const { h, app } = hyperapp const html = hyperx(h) const state = { greeting: "Hello,world" } const actions = {} const view = state => html`<h1 id="title">${state.greeting}</h1>` app(state, actions, view, document.body) </script> </body>

    浏览器中会发生什么呢?

    浏览器通过CDN下载了Hyperx和JSX,编译并渲染<script>部分,最终在页面上显示了“hello,world”。

  • Hyperapp 67 0 1 发布

    在这里,我们将结合示例介绍如何使用Hyperapp的模块和函数。

    Hyperapp主要提供了两大功能:

    h函数
    生成虚拟DOM的函数app函数
    使用Hyperapp执行应用程序的功能h()

    返回虚拟DOM的函数。 这里的虚拟DOM指的是以JavaScript对象表现的嵌套DOM树。

    name {String}
    「div」等HTML里的标签名props {Object}
    插入元素的属性值children {String | Array}
    子元素 h("a", { href: "#" }, "next page") // return object // { // name: 'a', // props: { // href: '#' // }, // children: 'next page' // } app()

    启动Hyperapp应用程序

    app(state, actions, view, container

    state

    管理应用程序状态的对象。 必需是一个纯JS对象。

    view

    返回虚拟DOM的函数。 以state和actions为参数

    const state = { on: true } const actions = { toggle: () => state => ({ on: !state.on }) } const view = (state, actions) => ( <button onclick={actions.toggle}>{state.on.toString()}</button> ) app(state, actions, view, document.body)

    actions

    定义应用程序行为的函数集合。 actions通常用于更新state。 其返回值通常是一个新的state

    const actions = { setValue: value => ({ value }), addValue: value => state => ({ value: state.value + value }), addValueLater: value => (state, actions) => { setTimeout(() => { actions.addValue(value) }, 1000) } } data
    actions处理(模型更新)所需的数据state
    当前stateactions
    应用程序的原始actions const state = { count: 0 } const actions = { sub: () => state => state - 1, add: () => state => state + 1 } const view = (state, actions) => ( <div> <h1>{state.count}</h1> <button onclick={actions.sub} disabled={state.count <= 0}> - </button> <button onclick={actions.add}>+</button> </div> ) app(state, actions, view, document.body)

    全局事件

    app函数返回的对象包含关联state的原始actions。 与传递给view的ctions相同,调用ctions时state会被更新。

    const state = { x: 0, y: 0 } const actions = { move: () => ({ x, y }) => ({ x, y }) } const view = state => <h1>{state.x + ", " + state.y}</h1> const MyApp = app(state, actions, view, document.body) addEventListener("mousemove", e => MyApp.move({ x: e.clientX, y: e.clientY }) )

    生命周期方法

    虚拟DOM提供了一些生命周期相关的事件

    oncreate
    Elment被加进DOMonupdate
    Element被更新onremove
    在Element从DOM中移除ondestroy
    Element被释放 const node = document.createElement("div") const editor = CodeMirror(node) const Editor = options => { const setOptions = options => Object.keys(options).forEach(key => editor.setOption(key, options[key])) const oncreate = elm => { setOptions(options) elm.appendChild(node) } const onupdate = _ => setOptions(options) return <div oncreate={oncreate} onupdate={onupdate} /> }
  • Vue 63 0 1 发布

    8.1. 前置知识学习npm 学习官方文档推荐资料npm入门npm介绍需要了解的知识点

    package.json

    文件相关配置选项

    npm 本地安装、全局安装、本地开发安装等区别及相关命令

    npm script脚步的基本编写能力

    有时间专门写一个这样的专题,如果需要可以邮件我。malun666@126.com

    webpack基础学习

    官方文档Webpack了解的知识点:webpack的基本配置了解webpack常用的loader: less-loader、sass-loader、 vue-loader、style-loader、css-loader、eslint-loader、babel-loader等熟悉Webpack的webpack-dev-server的基本配置和使用,会配置热更新

    es6语法学习

    阮一峰老师的大作《ECMAScript 6 入门》需要学习的知识点es6的模块机制各种最新语法糖,简写、geter、setter、箭头函数类、继承的心机制 ...

    nodejs基础知识

    知识点学习:文件操作http服务express

    组件化开发思想

    8.2. Vue脚手架工具:vue-cli构建实战项目

    其实如果编写Vue的前端项目,直接使用vue的官方vue-cli构建工具最好用,一个命令就可以直接生成项目的结构和目录。 而且官方需要依赖的包也可以自动配置好,只需要npm instal一下,然后就可以开发测试了。

    8.2.1. vue-cli安装# 安装vue-cli。 安装之前首先确保你已经安装好了nodejs 而且打开命令行 $ npm install -g vue-cli # 校验一下是否安装成功 $ vue -V #=> 2.5.1 我当前的版本是这个,你的可能比这个新 8.2.2. 使用vue-cli初始化项目

    通过以下命令的方式可以创建一个项目文件夹,并初始化对应的文件。

    $ vue init <template-name> <project-name>

    其中template-name可以取以下值,每个值对应不同的项目构建的模板。

    webpack--全功能的Webpack + vueify,包括热加载,静态检测,单元测试webpack-simple--一个简易的Webpack + vueify,以便于快速开始。browserify--全功能的Browserify + vueify,包括热加载,静态检测,单元测试browserify-simple--一个简易的Browserify + vueify,以便于快速开始。

    安装和开发控制台的命令:

    # 如果已经安装,请省略 $ npm install -g vue-cli # 初始化一个webpack全功能包的vue项目,请您把my-project换成你自己的项目名。 $ vue init webpack my-project # 用命令行进入当前项目目录 $ cd my-project # npm安装所有的依赖的包 $ npm install # 运行测试的首页 $ npm run dev 8.2.3. 综合实例开发记录通过vue-cli构建工具初始化项目目录

    安装过程,控制台会问你项目名称是什么?项目描述?项目作者,是否使用eslint校验,是否使用单元测试等....

    我的安装过程如下请参考:

    $ vue init webpack ttl # => 安装webpack模板的项目 ttl(项目名可以随便取) A newer version of vue-cli is available. latest: 2.6.0 installed: 2.5.1 This will install Vue 2.x version of template. For Vue 1.x use: vue init webpack#1.0 ttl ? Project name mydemovue # => 项目名称 ? Project description A Vue.js project # => 项目描述 ? Author malun <malun666@126.com> # => 作者 ? Vue build standalone # => 是否支持单文件组件 ? Use ESLint to lint your code? Yes # => 是否支持ESLint代码校验 ? Pick an ESLint preset Standard # => 校验的标准是什么? ? Setup unit tests with Karma + Mocha? Yes # => 是否使用单元测试 ? Setup e2e tests with Nightwatch? Yes # => 是否使用e2e测试 vue-cli · Generated "ttl". To get started: cd ttl npm install npm run dev Documentation can be found at https://vuejs-templates.github...

    通过上面一系列的命令后,我们就会创建一个webpack配置好的项目包。目录结构如下:

    ttl |--.babelrc #=> babel的配置文件,主要用于转换es6等最新的js语法。 |--.editorconfig #=> 编辑器配置 |--.eslintignore #=> eslint的忽略校验的配置文件 |--.eslintrc.js #=> eslint的配置校验js是否规范的配置文件 |--.gitignore #=> 设置git忽略的管理的文件 |--README.md #=> readme说明文件 |--build/ #=> 自动构建存放的文件地方 |--config/ #=> 当前开发、测试等配置的文件,需要懂点nodejs了啊。 |--index.html #=> 项目的主入口的模板 |--package.json #=> npm的配置文件 |--src/ #=> 源码目录 |--static/ #=> 静态资源存放的目录 |--test/ #=> 测试相关目录 初始化依赖包$ cd ttl #=> 进入上面创建好的项目目录 $ npm install #=> 安装所有的依赖包。 安装过程可能非常长,网络也可能有问题,请耐心等待。 # 安装完成后,可以直接运行测试,如果自动打开浏览器,并跳转到http://localhost:8080/ 说明一切都ok了。 $ npm run dev

    npm 安装的时候经常网会断开,国内的网(哎,说多了都是泪)你懂的。最好能科学上网,或者是用淘宝的npm的镜像

    安装vue-router组件$ npm i -S vue-router

    到项目的

    /src/components/

    目录下创建三个组件文件。

    分别是:

    首页组件

    <template> <div class="home"> <h3>{{ msg }}</h3> </div> </template> <script> export default { name: 'home', // 组件可以有自己的名字。 data () { // 组件的data必须是函数 return { msg: '这里是Home视图' } } } </script> <style scoped> h3 { background-color: #82c; } </style>

    用户首页组件

    <template> <div> <h3>{{ msg }}</h3> </div> </template> <script> export default { // es6的模块导出定义语法,此模块导出默认的对象 name: 'user', // 组件可以有自己的名字。 data () { // 组件的data必须是函数 return { msg: '这里是User视图' } } } </script> <style scoped> h3 { background-color: red; } </style>

    产品组件

    <template> <div class="product"> <h3>{{ msg }}</h3> </div> </template> <script> export default { name: 'product', // 组件可以有自己的名字。 data () { // 组件的data必须是函数 return { msg: '这里是Home视图' } } } </script> <style scoped> h3 { background-color: green; } </style>

    项目的目录结构为:

    ttl |-- src |--|-- Hello.vue |--|-- Home.vue |--|-- Product.vue |--|-- User.vue 创建router对象及配置路由

    在src目录下创建approuter.js文件。 然后添加如下代码:

    import VueRouter from 'vue-router' // 导入路由模块 import Home from './components/Home.vue' // 导入Home组件 import User from './components/User.vue' import Product from './components/Product.vue' export default new VueRouter({ // 定义路由规则对象 routes: [ {path: '/home', component: Home}, {path: '/user/:id', component: User}, {path: '/product/:id', component: Product} ] }) 修改main.js文件 找到src/目录下的main.js文件, 共修改4处,添加路由引用、添加路由规则对象导入、启用路由、将路由键入到Vue中。
    修改此文件为:// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import VueRouter from 'vue-router' // +++1、导入路由组件 import router from './approuter' // +++2、导入我们自己写的路由配置文件 // +++ 3、使用路由组件 Vue.use(VueRouter) /* eslint-disable no-new */ new Vue({ el: '#app', template: '<App/>', components: { App }, router: router // +++4、添加路由对象 }) 在app.vue中添加路由导航

    最终代码如下:

    <template> <div id="app"> <nav class="top-menu"> <ul > <li v-for="item in menuList"> <router-link :to="item.url">{{ item.name }}</router-link> </li> </ul> </nav> <hr> <div> <router-view></router-view> </div> </div> </template> <script> export default { name: 'app', data: function () { return { menuList: [ { name: '首页', url: '/home' }, { name: '用户', url: '/user/19' }, { name: '产品', url: '/product/20' } ] } } } </script> <style> #app { } .top-menu ul, .top-menu li { list-style: none; } .top-menu { overflow: hidden; } .top-menu li { float: left; width: 100px; } </style>  

    刷新一下浏览器,你将会看到最终的运行结果。


    转载:https://www.cnblogs.com/fly_dr...

    作者:老马

  • Hyperapp 61 0 1 发布

    Web应用程序的开发环境包括三个要素:

    Package Manager(例如:npm,yarn)Complier(例如:babel,Buble)Bundler(例如:Webpack, Browserify, Rollup)

    之所以需要这些,是因为要编译用JSX/ Hyperx编写的源代码,当编译时,它成为生成虚拟DOM的函数,称为Hyperapp的h函数。

    编译前(JSX/Hyperx)

    <h1 id="test">Hi.</h1>

    编译后

    h("h1", { id: "test" }, "Hi.")

    JSX开发环境

    JSX采用与XML同样的记法,通过JSX您可以将HTML(模板)和JavaScript(处理)混合在一个文件中。
    要使用JSX,您需要如上所述进行编译。 您必须将JSX转换为h函数,将其打包为一个js文件,然后进行发布。

    如果是使用Browserify

    安装必要的模块

    npm i -S hyperapp npm i -D babel-plugin-transform-react-jsx babel-preset-es2015 babelify browserify bundle-collapser uglifyify uglifyjs

    准备.babelrc文件

    { "presets": ["es2015"], "plugins": [ [ "transform-react-jsx", { "pragma": "h" } ] ] }

    编译打包

    browserify \ -t babelify \ -g uglifyify \ -p bundle-collapser/plugin index.js | uglifyjs > bundle.js

    如果是使用Webpack

    安装必要的模块

    npm i -S hyperapp npm i -D babel-plugin-transform-react-jsx babel-preset-es2015 babelify browserify bundle-collapser uglifyify uglifyjs

    准备.babelrc文件

    { "presets": ["es2015"], "plugins": [ [ "transform-react-jsx", { "pragma": "h" } ] ] }

    准备webpack.config.js文件

    module.exports = { entry: "./index.js", output: { filename: "bundle.js" }, module: { loaders: [ { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" } ] } }

    编译打包

    webpack -p

    如果是使用Rollup

    安装必要的模块

    npm i -S hyperapp npm i -D rollup rollup-plugin-babel rollup-plugin-node-resolve rollup-plugin-uglify babel-preset-es2015-rollup babel-plugin-transform-react-jsx

    准备rollup.config.js文件

    import babel from "rollup-plugin-babel" import resolve from "rollup-plugin-node-resolve" import uglify from "rollup-plugin-uglify" export default { plugins: [ babel({ babelrc: false, presets: ["es2015-rollup"], plugins: [["transform-react-jsx", { pragma: "h" }]] }), resolve({ jsnext: true }), uglify() ] }

    编译打包

    rollup -cf iife -i index.js -o bundle.js

    Hyperx开发環境

    编辑中(基本与JSX开发环境相似,仅一些地方安装的模块有些不同)

  • Vue 50 0 1 发布

    4.1. 监听事件的Vue处理

    Vue提供了协助我们为标签绑定时间的方法,当然我们可以直接用dom原生的方式去绑定事件。Vue提供的指令进行绑定也是非常方便,而且能让ViewModel更简洁,逻辑更彻底。所以还是推荐大家使用的。

    Vue提供了v-on指令帮助我们进行事件的绑定。 基本的内联事件处理方法[官方demo]:

    <div id="example-1"> <!-- 为按钮绑定点击事件,执行counter += 1的任务。 --> <button v-on:click="counter += 1">增加 1</button> <p>这个按钮被点击了 {{ counter }} 次。</p> </div> <script> var example1 = new Vue({ el: '#example-1', data: { counter: 0 } }) </script> 4.2. 事件处理方法集成到Vue对象

    内联的方式绑定的事件,只能处理简单的事件的处理逻辑。复杂的情况还是封装到js中最方便,也不容易出错。 Vue对象中可以添加methods属性,开发者可以把事件处理函数的逻辑放到methods中。

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue入门之动态显示表格</title> <script src="https://unpkg.com/vue/dist/vue.js"></script> </head> <body> <div id="app"> <p>{{ number }}</p> <input type="button" name="btnGetNumber" value="增加[绑定事件处理器]" v-on:click="getNumber"> <input type="button" name="btnGetNumber" value="增加[内联方法调用]" v-on:click="getNumber()"> </div> <script> var app = new Vue({ el: '#app', data: { number: 1 }, methods: { // 事件响应方法的逻辑代码 getNumber: function (e) { this.number += 1; // 不管是内联方法调用,还是绑定事件处理器两种方式执行事件响应方法的时候 this都是指向 app } } }); </script> </body> </html> 4.3. 事件修饰符

    官网上写的非常好,这块就直接用管网的吧。在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。尽管我们可以在 methods 中轻松实现这点,但更好的方式是:methods 只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。 为了解决这个问题, Vue.js 为 v-on 提供了 事件修饰符。通过由点(.)表示的指令后缀来调用修饰符。

    .stop.prevent.capture.self.once <!-- 阻止单击事件冒泡 --> <a v-on:click.stop="doThis"></a> <!-- 提交事件不再重载页面 --> <form v-on:submit.prevent="onSubmit"></form> <!-- 修饰符可以串联 --> <a v-on:click.stop.prevent="doThat"></a> <!-- 只有修饰符 --> <form v-on:submit.prevent></form> <!-- 添加事件侦听器时使用事件捕获模式 --> <div v-on:click.capture="doThis">...</div> <!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 --> <div v-on:click.self="doThat">...</div> <!-- the click event will be triggered at most once --> <a v-on:click.once="doThis"></a>
    4.4. 按键修饰符

    在监听键盘事件时,我们经常需要监测常见的键值。 Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:

    <!-- 只有在 keyCode 是 13 时调用 vm.submit() --> <input v-on:keyup.13="submit"> 记住所有的 keyCode 比较困难,所以 Vue 为最常用的按键提供了别名: <!-- 同上 --> <input v-on:keyup.enter="submit"> <!-- 缩写语法 --> <input @keyup.enter="submit">

    全部的按键别名:

    .enter.tab.delete (捕获 “删除” 和 “退格” 键).esc.space.up.down.left.right.ctrl.alt.shift.meta4.5. 事件绑定的简写

    Vue中属性的绑定的简写直接是: === 'v-bind:'
    而事件的缩写是直接变成@. 也就是说: v-on: === @ 看下面的例子: 

    <!-- 完整语法 --> <a v-on:click="doSomething"></a> <!-- 缩写 --> <a @click="doSomething"></a> 4.6. 事件绑定总结

    Vue为了方便大家进行开发,提供了事件的相关的封装,可以让我们方便我们用Vue对事件进行开发,尤其是v-on指令的非常方便的跟Vue对象中methods进行配合进行复杂的事件处理,非常方便。另外事件的事件修饰符和按键修饰符也可以让Vue事件这块锦上添花。

    转载:https://www.cnblogs.com/fly_dr...

    作者:老马

  • Backbone 47 0 1 发布

    Backbone视图可以使用JavaScript模板,根据模型数据的逻辑处理向用户展示相应的界面。可以监听模型的change事件,并在回调函数绑定视图的render()方法,就可以在不重绘整个页面的情况下,更新视图。

    创建视图

    可以通过扩展Backbone.View对象创建一个视图:

    var app = app || {}; app.MenuListView = Backbone.View.extend({ tagName: 'ul', className: 'menu-list', template: function() { return _.template('<li><%= title %></li>'); }, render: function() { this.$el.html(this.template()({title: "Menu List"})); return this; }, initialize: function() { this.render(); $('body').append(this.$el); } }); app.menulist = new app.MenuListView(); console.log(app.menulist.el); console.log(app.menulist.$el);

    打印值如下:

    app.menulist.el:

    app.menulist.$el:

    初始化

    如果视图定义了initialize()初始化函数,在创建视图时,它将立即被调用。

    视图与模型

    创建视图时,可以通过传入model或collection属性和值,将某一模型或集合直接注册到视图中:

    var app = app || {}; app.MenuModel = Backbone.Model.extend({ defaults: { title: 'this is a menu', status: 'inactive' } }); app.MenuCollection = Backbone.Collection.extend({ model: app.MenuModel, initialize: function() { console.log('集合初始化成功'); } }); var menus = [ { id: 1, name: '最近会话', status: 'active' }, { id: 2, name: '通讯录', status: 'inactive' } ] app.menus = new app.MenuCollection(menus); app.MenuListView = Backbone.View.extend({ tagName: 'ul', className: 'menu-list', template: function() { return _.template('<li><%= title %></li>'); }, render: function() { this.$el.html(this.template()({title: "Menu List"})); return this; }, initialize: function() { //console.log('视图初始化'); this.render(); $('body').append(this.$el); } }); app.menulist = new app.MenuListView({ collection: app.menus }); console.log(app.menulist.collection);

    打印如下:

    视图与DOM

    我们希望通过使用Backbone视图生成页面文档,将页面展示给用户,就必须将视图与DOM关联起来,通过操作视图改变DOM。

    Backbone提供两种方式关联视图和DOM:

    创建

    创建视图时创建一个新元素,然后将该元素插入至DOM。

    引用

    视图直接引用页面已经存在的元素。

    创建

    Backbone视图创建元素时只需要使用tagName、id、className属性。此Backbone视图对象的el属性是一个指向该元素的引用。

    tagName默认值为div。

    app.MenuListView = Backbone.View.extend({ tagName: 'ul', //元素标签类型,必选,未设置时默认为div className: 'menu-list', //元素class,可选 id: 'menus', //元素id,可选 initialize: function() { $('body').append(this.$el); } }); app.menulist = new app.MenuListView(); console.log(app.menulist.el); //logs: <ul id="menus" class="menu-list"></ul>

    引用
    可以为Backbone视图对象传入一个el属性,来匹配页面文档已存在的元素。

    app.MenuListView = Backbone.View.extend({ el: 'body', //值为CSS选择器 initialize: function() { } }); app.menulist = new app.MenuListView(); console.log(app.menulist.el); //logs: <body>...</body>

    我们也可以在创建视图时,为对象el属性设置值:

    app.menulist = <span class="hljs-keyword">new</span> app.MenuListView({el: <span class="hljs-string">'body'</span>});

    el属性值为CSS选择器,Backbone视图对象将根据此选择器匹配页面元素。

    视图属性与方法

    要深入理解Backbone视图,必须理解视图一些重要的属性和方法。

    el

    el是视图的一个核心属性,也是使用视图对象时必然会用到的一个属性。

    el是DOM元素的一个引用,所有视图都有其el属性。视图可以通过使用el构成它的元素内容,在触发浏览器最少次数重排和重绘的情况下,将所有内容一次性插入文档DOM。

    $el、$()

    对视图和DOM操作,经常要用到jQuery函数,Backbone通过为视图定义$el属性和$()函数,为我们操作视图和DOM提供了很多便利。视图的$el属性等价于$(View.el),$(selector)等价于$(View.el).find(selector)。

    setElement()
    Backbone提供setElement()方法,支持将现有Backbone视图应用于不同的DOM元素,调用该方法将创建一个缓存$el引用,并且将视图委托事件从旧元素移动到新元素。

    var MyView = Backbone.View.extend({ events: { click: function(e) { console.log(myView.$el.html()); } } }); var btn1 = $('<button>button 1</button>'); var btn2 = $('<button>button 2</button>'); //视图元素el是btn1 var myView = new MyView({el: btn1}); btn1.trigger('click'); //logs: button 1 //视图元素el指向btn2 myView.setElement(btn2); btn1.trigger('click'); btn2.trigger('click'); //logs: button 2 console.log(myView.$el.html);// button 2

    渲染模板-render()

    render()函数是一个可选函数,需要我们主动调用,通常我们在里面实现根据模型属性渲染视图模板,生成HTML标记;然后使用el或$el属性,将这些HTML标记设置为视图的el属性所引用的 DOM元素的HTML内容。

    app.MenuModel = Backbone.Model.extend({ defaults: { title: 'this is a menu', status: 'inactive' } }); app.MenuCollection = Backbone.Collection.extend({ model: app.MenuModel, initialize: function() { console.log('集合初始化成功'); this.on('reset', function(cols, options) { console.log('重置集合'); }, this); this.on('add', function(model) { console.log('添加模型,cid: ' + model.cid); }); this.on('change', function(model) { console.log('模型属性改变为: ' + model.get('name'), model); }); this.on('change:name', function(model) { console.log('模型name属性改变为: ' + model.get('name')); }); this.on('remove', function(model) { console.log('移除模型: ' + model.cid); }); } }); var menus = [ { id: 1, name: '最近会话', status: 'active' }, { id: 2, name: '通讯录', status: 'inactive' } ] app.menus = new app.MenuCollection(menus); app.MenuItemView = Backbone.View.extend({ tagName: 'li', className: 'menu-item', template: function() { return _.template('<a title="<%= title %>"><%= name %></a>'); }, render: function() { this.$el.html(this.template()(this.model.toJSON())); return this; } }); app.MenuListView = Backbone.View.extend({ tagName: 'ul', className: 'menu-list', template: function() { return _.template(''); }, render: function() { //遍历集合,集合中每个模型对应一个菜单项 _.each(this.collection.models, function(model) { //为每个集合模型,创建一个新菜单项视图实例 var menuItemView = new app.MenuItemView({model: model}); //在父视图-菜单列表视图中添加子菜单-菜单项视图 this.$el.append(menuItemView.render().el); }, this); console.log(this.el); return this; }, initialize: function() { this.render(); $('body').append(this.$el); } }); app.menulistview = new app.MenuListView({ collection: app.menus });

    控制台打印值如下:

    页面效果如图:

    我们通常在render()函数底部返回this以开启链式调用,该视图可以在其他父视图里被重用。

    Events对象

    Backbone提供events对象支持我们通过设置在el下的自定义CSS选择器、事件类型和事件监听器,为DOM元素绑定事件。

    app.MenuItemView = Backbone.View.extend({ tagName: 'li', className: 'menu-item', events: { 'click .menu': 'openMenu', 'dblclick .menu': 'edit' }, template: function() { return _.template('<a class="menu" title="<%= title %>"><%= name %></a>'); }, render: function() { this.$el.html(this.template()(this.model.toJSON())); return this; }, initialize: function() { this.dbltimer = null; }, openMenu: function(e) { if (this.dbltimer) { clearTimeout(this.dbltimer); this.dbltimer = null; } this.dbltimer = setTimeout(function(){ console.log('opened'); },300); }, edit: function(e) { if (this.dbltimer) { clearTimeout(this.dbltimer); this.dbltimer = null; } console.log('edit'); } }); app.MenuListView = Backbone.View.extend({ tagName: 'ul', className: 'menu-list', template: function() { return _.template(''); }, render: function() { _.each(this.collection.models, function(model) { var menuItemView = new app.MenuItemView({model: model}); this.$el.append(menuItemView.render().el); }, this); // this.$el.html(this.template()({title: "Menu List"})); console.log(this.el); return this; }, initialize: function() { this.render(); $('body').append(this.$el); } }); app.menulistview = new app.MenuListView({ collection: app.menus });

    若没有设置CSS选择器,则默认为el所引用DOM元素绑定事件。

    移除视图-remove()

    调用View.remove(),从DOM中移除一个视图。同时将调用stopListening来移除通过 listenTo绑定在视图上的所有事件。

    app.menulistview.remove();

    声明: 本文转载自熊建刚的博客

  • Vue 47 0 1 发布
    1.1. Vue简介

    Vue是一个前端的双向绑定类的框架,发音[读音 /vjuː/, 类似于 view]。新的Vue版本参考了React的部分设计,当然也有自己独特的地方,比如Vue的单文件组件开发方式都很有创新,另外Vue自身的一些绑定的语法、用法等都非常精炼,很容易上手,而且第三方的插件都非常丰富,社区非常活跃,最新的文档都有中文版本。而且Vue配合官方的和第三方的库可以实现单文件的组件化开发、SPA等现代化前端开发。

    1.2. Vue的入门demo

    Vue 可以直接把它当做一个js库使用,所以它可以很容易的接入到你的项目或者单个页面中。甚至你可以只使用它的双向绑定功能。所以它很容易上手。

    比如:我们有一个需求,一个网页上一个Div标签,我们有一个json对象存储数据,把json对象上的数据放到Div上去。

    接下来是步骤:

    第一步: 创建一个文件夹并创建一个html文件 比如:index.html.
    当如你可以选择你自己的编辑器,我就用VSCode。第二步:引入Vue库
    当然了你可以直接下载Vue的js文件,推荐你直接用上面的cdn即可。第三步:创建一个Div,给它一个id,比如:app第四步:创建Vue的对象,并把数据绑定到上面创建好的div上去。

    最终的代码如下:

    <!DOCTYPE html> <!--第一步:创建文件夹及html文件--> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue入门之Helloworld</title> <!--第二步:引入Vue库--> <script src="https://unpkg.com/vue/dist/vue.js"></script> </head> <body> <!--第三步:创建一个Div--> <div id="app"> <!--Vue的模板的绑定数据的方法, 类似于很多其他前端的模板,可以用两对花括号进行绑定Vue中的数据对象的属性 --> {{ message }} </div> <!--第四步:创建Vue的对象,并把数据绑定到上面创建好的div上去。--> <script> var app = new Vue({ // 创建Vue对象。Vue的核心对象。 el: '#app', // el属性:把当前Vue对象挂载到 div标签上,#app是id选择器 data: { // data: 是Vue对象中绑定的数据 message: 'Hello Vue!' // message 自定义的数据 } }); </script> </body> </html> 

    最终的结果就是:

    Hello Vue!1.3. Vue的Helloworld总结Vue构造函数的:选项el属性,就是element缩写,当前Vue对象挂载到哪个标签上的语法,支持CSS选择器或者dom对象,一般用id选择器选择当前页面的标签。Vue的选项:data属性是自定义数据。这里我们只是演示了一个message属性,vue会把自定义的数据可以与html的模板数据进行绑定。Vue 数据绑定的方式就是用 {{}},类似于handlebars.上面这个demo就是演示了Vue的绑定数据的基本模型。注意点,标签先创建好了之后,再创建Vue对象,具体你应该懂吧。

    转载:https://www.cnblogs.com/fly_dragon/p/6218551.html

    作者:老马

  • React 46 0 1 发布

    Hook是React16.8的新增特性。它可以让我们在不使用类语法(class)的情况下编写有状态组件(Stateful Component)。

    Hook将React哲学(显式数据流和组合)引入到组件内部,而不仅仅是组件之间。使用这一方案可以让组件内部的代码逻辑更为清晰条理化。

    下面首先通过对class组件的改造来了解Hook的适用法。

    首先是一个简单的SubmitButton组件:

    import React, { Component } from "react"; export default class SubmitButton extends Component { constructor(props) { super(props); this.state = { text: "click me!" }; this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState(() => { return { text: "loading..." }; }); setTimeout(() => { this.setState(() => ({text: "submited!"})) }, 3000); } render() { const { text } = this.state; return (<button onClick={this.handleClick}>{text}</button>); } }

    SubmitButton组件,通过自己的state管理显示文本。

    import React, { Component } from 'react'; import Button from "./SubmitButton" class FormComponent extends Component {

    state = {
    name: 'honwlee',
    age: 33
    }

    handleNameChange = (firstName) => {
    this.setState({ firstName })
    }

    handleLastNameChange = (lastName) => {
    this.setState({ lastName })
    }
    handleAgeChange = (age) => {
    this.setState({ age })
    }
    onSubmit = (e) => {
    e.preventDefault();
    }

    render () {
    return (
    <React.Fragment>
    <form>
    <input
    name="name"
    type="text"
    onChange={(e) => this.handleNameChange(e.target.value)}
    value={this.state.name}
    />

    &lt;input name="age" type="number" onChange={(e) =&gt; this.handleAgeChange(e.target.value)} value={this.state.age} /&gt; &lt;Button&gt;&lt;/Button&gt; &lt;/form&gt; &lt;/React.Fragment&gt; )

    }
    };
    export default FormComponent;