热门总结

  • Hyperapp 182 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”。

  • Vue 104 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...

    作者:老马

  • Vue 101 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...

    作者:老马

  • Hyperapp 98 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} /> }
  • Hyperapp 96 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开发环境相似,仅一些地方安装的模块有些不同)

  • React 94 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;

  • Backbone 93 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 91 0 1 发布
    2.1. 什么是双向绑定?

    Vue框架很核心的功能就是双向的数据绑定。 双向是指:HTML标签数据 绑定到 Vue对象,另外反方向数据也是绑定的。通俗点说就是,Vue对象的改变会直接影响到HTML的标签的变化,而且标签的变化也会反过来影响Vue对象的属性的变化。
    这样以来,就彻底变革了之前Dom的开发方式,之前Dom驱动的开发方式尤其是以jQuery为主的开发时代,都是dom变化后,触发js事件,然后在事件中通过js代码取得标签的变化,再跟后台进行交互,然后根据后台返回的结果再更新HTML标签,异常的繁琐。有了Vue这种双向绑定,让开发人员只需要关心json数据的变化即可,Vue自动映射到HTML上,而且HTML的变化也会映射回js对象上,开发方式直接变革成了前端由数据驱动的 开发时代,远远抛弃了Dom开发主导的时代了。

    2.2. Vue绑定文本

    数据绑定最常见的形式就是使用 “Mustache” 语法(双大括号)的文本插值,比如模板引擎:handlebars中就是用的{{}}.
    创建的Vue对象中的data属性就是用来绑定数据到HTML的。参考如下代码:

    <span>Message: {{ msg }}</span> <script> var app = new Vue({ // 创建Vue对象。Vue的核心对象。 el: '#app', // el属性:把当前Vue对象挂载到 div标签上,#app是id选择器 data: { // data: 是Vue对象中绑定的数据 msg: 'Hello Vue!' // message 自定义的数据 } }); </script> 2.3. 绑定数据中使用JavaScript表达式

    对于所有的数据绑定, Vue.js 都提供了完全的 JavaScript 表达式支持。

    <span>Message: {{ msg + ' - ' + name }}</span> <script> var app = new Vue({ // 创建Vue对象。Vue的核心对象。 el: '#app', // el属性:把当前Vue对象挂载到 div标签上,#app是id选择器 data: { // data: 是Vue对象中绑定的数据 msg: 'Hi', // message 自定义的数据 name: 'flydragon' // name自定义的属性,vue可以多个自定义属性,属性类型也可是复杂类型 } }); </script>

    结果:

    Hi - flydragon

    当然Vue还可以支持表达中的任何计算、函数处理等。参考下面的综合点的案例。

    <!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"> {{ msg + ' - ' + name }} <p> {{ isOk ? '123' : '456' }} </p> <p>我的年龄是: {{ age *2 }}</p> </div> <script> var app = new Vue({ // 创建Vue对象。Vue的核心对象。 el: '#app', // el属性:把当前Vue对象挂载到 div标签上,#app是id选择器 data: { // data: 是Vue对象中绑定的数据 msg: 'Hi', // message 自定义的数据 name: 'flydragon', isOk: true, age: 18 } }); </script> </body> </html> 2.4. Vue属性绑定

    Vue中不能直接使用{{ expression }} 语法进行绑定html的标签,而是用它特有的v-bind指令(就是一种写法,先按照格式走,具体指令是什么可以后续再了解)。

    绑定的语法结构:

    <span v-bind:id="menuId">{{ menuName }}</span>

    参考如下代码案例:

    <!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"> <div v-bind:id="MenuContaineId"> <a href="#" v-bind:class="MenuClass">首页</a> <a href="#" v-bind:class="MenuClass">产品</a> <a href="#" v-bind:class="MenuClass">服务</a> <a href="#" v-bind:class="MenuClass">关于</a> </div> </div> <script> var app = new Vue({ el: '#app', data: { // data: 是Vue对象中绑定的数据 MenuClass: 'top-menu', MenuContaineId: 'sitemenu' } }); </script> </body> </html> 2.5. 属性绑定简写

    由于v-bind 使用非常频繁,所以Vue提供了简单的写法,可以去掉v-bind直接使用:即可。例如:

    <div :id="MenuContaineId">

    等价于:

    <div v-bind:id="MenuContaineId"> 2.6. 输出纯HTML

    由于Vue对于输出绑定的内容做了提前encode,保障在绑定到页面上显示的时候不至于被xss攻击。但某些场景下,我们确保后台数据是安全的,那么我们就要在网页中显示原生的HTML标签。Vue提供了v-html指令。

    <div id="app"> <div v-bind:id="MenuContaineId" v-html="MenuBody"> </div> </div> <script> var app = new Vue({ el: '#app', data: { // data: 是Vue对象中绑定的数据 MenuContaineId: 'menu', MenuBody: '<p>这里是菜单的内容</p>' } }); </script>

    结果:

    <div id="app"> <div id="menu"> <p>这里是菜单的内容</p> </div> </div> 2.7. 样式绑定

    对于普通的属性的绑定,只能用上面的讲的绑定属性的方式。而Vue专门加强了class和style的属性的绑定。可以有复杂的对象绑定、数组绑定样式和类。

    2.7.1. 绑定样式对象

    经常我们需要对样式进行切换,比如:div的显示和隐藏,某些标签active等。Vue提供的对象绑定样式的方式就很容做这些事情。

    代码: 

    <div v-bind:class="{ active: isActive }"></div> 解释:当 isActive为 true时, div就会具有了active样式类,如果 isActive为false,那么div就去掉active样式类。<span></span> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue入门之绑定样式类</title> <script src="https://unpkg.com/vue/dist/vue.js"></script> <style> .active { background-color: #ccc; } </style> </head> <body> <div id="app"> <div v-bind:id="MenuContaineId" v-bind:class="{ active: isActive }"> 绑定颜色类 </div> </div> <script> var app = new Vue({ el: '#app', data: { // data: 是Vue对象中绑定的数据 MenuContaineId: 'menu', isActive: true } }); </script> </body> </html> 

    解释: 当 isActive为 true时, div就会具有了active样式类,如果 isActive为false,那么div就去掉active样式类。

    2.7.2. 混合普通的HTML标签样式类及绑定样式对象

    v-bind:class 指令可以与普通的 class 属性共存。

    <div id="app"> <div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }"> </div> </div> <script> var app = new Vue({ el: '#app', data: { // data: 是Vue对象中绑定的数据 isActive: true, hasError: false } }); </script>

    结果:

    <div id="app"> <div class="static active"> </div> </div> 2.7.3. 绑定data中的样式对象

    直接在html属性中的双引号内写对象,还是很不爽,也没有智能提示,很容易写错。 Vue可以让我们直接把绑定的class字符串指向data的一个对象,这样就非常方便了,既可以有智能提示,又可以很复杂进行编辑,不用担心烦人的""了。

    <div id="app"> <div class="static" v-bind:class="classObject"> </div> </div> <script> var app = new Vue({ el: '#app', data: { classObject: { active: true, 'text-danger': false } } }); </script>

    结果:

    <div id="app"> <div class="static active"> </div> </div> 2.7.4. 绑定样式数组

    其实绑定数组,就是绑定样式对象的延续,看官网的例子代码吧。

    <div v-bind:class="[activeClass, errorClass]"> data: { activeClass: 'active', errorClass: 'text-danger' }

    当然还有很多其他很有趣的支持,就不赘述了。例如:

    例如: <div v-bind:class="[isActive ? activeClass : '', errorClass]"> <div v-bind:class="[{ active: isActive }, errorClass]"> 2.7.5. 内联样式绑定

    内联样式的绑定,非常类似于样式类的操作。v-bind:style 的对象语法十分直观——看着非常像 CSS ,其实它是一个 JavaScript 对象。 CSS属性名可以用驼峰式(camelCase)或短横分隔命名(kebab-case)。

    看个例子:

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue入门之htmlraw</title> <script src="https://unpkg.com/vue/dist/vue.js"></script> </head> <body> <div id="app"> <div v-bind:style="{fontSize: size + 'px', backgroundColor: bgcolor, width: width}"> vue 入门系列教程 </div> </div> <script> var app = new Vue({ el: '#app', data: { size: 19, width: 200, bgcolor: 'red' } }); </script> </body> </html>

    自动添加前缀
    当 v-bind:style 使用需要特定前缀的 CSS 属性时,如 transform ,Vue.js 会自动侦测并添加相应的前缀。

    2.8. 计算属性

    在做数据的绑定的时候,数据要进行处理之后才能展示到html页面上,虽然vue提供了非常好的表达式绑定的方法,但是只能应对低强度的需求。比如: 把一个日期按照规定格式进行输出,可能就需要我们对日期对象做一些格式化的出来,表达式可能就捉襟见肘了。

    Vue对象提供的computed属性,可以让我们开发者在里面可以放置一些方法,协助我们绑定数据操作,这些方法可以跟data中的属性一样用,注意这些方法用的时候不要加()。 例子来了:

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue入门之htmlraw</title> <script src="https://unpkg.com/vue/dist/vue.js"></script> </head> <body> <div id="app"> <table> <tr> <!-- computed里面的函数可以直接当成data里面的属性用,非常方便,注意没有括号!!!--> <td>生日</td><td>{{ getBirthday }}</td> </tr> <tr> <td>年龄</td><td>{{ age }}</td> </tr> <tr> <td>地址</td><td>{{ address }}</td> </tr> </table> </div> <script> var app = new Vue({ el: '#app', data: { birthday: 914228510514, // 这是一个日期对象的值:1998年11月1日 age: 19, address: '北京昌平区龙泽飞龙' }, computed: { // 把日期换成 常见规格格式的字符串。 getBirthday: function () { var m = new Date(this.birthday); return m.getFullYear() + '年' + m.getMonth() +'月'+ m.getDay()+'日'; } } }); </script> </body> </html> 2.9. 绑定的数据过滤器

    过滤器本质就是数据在呈现之前先进行过滤和筛选。官网上写的不错,我就不再赘述,下面是官网的描述。

    Vue.js 允许你自定义过滤器,被用作一些常见的文本格式化。过滤器应该被添加在 mustache 插值的尾部,由“管道符”指示:

    {{ message | capitalize }} <!-- in mustaches --> {{ message | capitalize }} <!-- in v-bind --> <div v-bind:id="rawId | formatId"></div> Vue 2.x 中,过滤器只能在 mustache 绑定和 v-bind 表达式(从 2.1.0 开始支持)中使用,因为过滤器设计目的就是用于文本转换。为了在其他指令中实现更复杂的数据变换,你应该使用计算属性。 过滤器函数总接受表达式的值作为第一个参数。 new Vue({ // ... filters: { capitalize: function (value) { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) } } }) 过滤器可以串联: {{ message | filterA | filterB }} 过滤器是 JavaScript 函数,因此可以接受参数: {{ message | filterA('arg1', arg2) }} 这里,字符串 'arg1' 将传给过滤器作为第二个参数, arg2 表达式的值将被求值然后传给过滤器作为第三个参数。 2.10. 核心:自动响应对象的变化到HTML标签

    上面的例子都是 数据对象是写死在创建的Vue对像上,那如果数据(data)发生改变时会怎样呢? 让我们用chrome把上面例子的页面打开,并打开发者工具控制台,输入:app.age = 20 会有什么情况发生呢?

     

    在页面中添加一个按钮,动态的增加年龄:

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue入门之htmlraw</title> <script src="https://unpkg.com/vue/dist/vue.js"></script> </head> <body> <div id="app"> <table> <tr> <!-- computed里面的函数可以直接当成data里面的属性用,非常方便,注意没有括号!!!--> <td>生日</td><td>{{ getBirthday }}</td> </tr> <tr> <td>年龄</td><td>{{ age }}</td> </tr> <tr> <td>地址</td><td>{{ address }}</td> </tr> </table> </div> <!-- 添加下面这行代码,动态增加 年龄,页面会有怎样的变化呢?? --> <button type="button" onclick="app.age+=1;" >加加</button> <script> var app = new Vue({ el: '#app', data: { birthday: 914228510514, // 这是一个日期对象的值:1998年11月1日 age: 19, address: '北京昌平区龙泽飞龙' }, computed: { // 把日期换成 常见规格格式的字符串。 getBirthday: function () { var m = new Date(this.birthday); return m.getFullYear() + '年' + m.getMonth() +'月'+ m.getDay()+'日'; } } }); </script> </body> </html> 2.11. 双向数据绑定

    上面的例子我们大多讲的是单向的 js对象向 HTML数据进行绑定,那HTML怎样向js进行反馈数据呢? HTML中只有表达能接受用户的输入,最简单的演示双向绑定的就是文本框了。

    Vue提供了一个新的指令:v-model进行双向数据的绑定,注意不是v-bind。

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Vue入门之htmlraw</title> <script src="https://unpkg.com/vue/dist/vue.js"></script> </head> <body> <div id="app"> <!-- v-model可以直接指向data中的属性,双向绑定就建立了 --> <input type="text" name="txt" v-model="msg"> <p>您输入的信息是:{{ msg }}</p> </div> <script> var app = new Vue({ el: '#app', data: { msg: '双向数据绑定的例子' } }); </script> </body> </html>

    最终的结果就是:你改变input文本框的内容的时候,p标签中的内容会跟着进行改变,哇是不是很神奇呢...

    关于其他表单的绑定的语法我就不赘述了,还是参考官网吧,我这里大部分例子也是来自官网

    2.12. 数据绑定总结

    vue提供了大量的绑定的语法和方法,非常方便我们进行数据的绑定,尤其它是双向的数据绑定,极大的减少了我们dom操作的麻烦程度。可能你越来越喜欢它了吧...

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

    作者:老马