前端及开发文章及欣赏

Vue 插槽之 作用域插槽

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

现在我有如下需求,子组件 <user /> 中此时有一条用户的信息(userInfo);我要在父组件通过插槽展示这个用户的姓名(userInfo.name);

注意:这里的父组件并没有这个用户的信息,子组件中有,如果直接在父组件{{userInfo.name}} 获取这条信息是获取不到的;因为,只有 <user /> 组件可以访问到 userInfo,而我们提供的内容是在父组件渲染的;
模板在哪写,就是用哪里的变量,跟插槽用在哪无关
模板是在父组件中写好,被编译过后,传到子组件的插槽中的

为了让父组件的插槽内容可以读取到子组件的数据,我们可以将userInfo 作为一个 <slot> 元素的特性绑定上去;

// 子组件
const card = {
    data() {
        return {
            userInfo: {name: '宫鑫'}
        }
    },
    template: `
    <div class='card'>
        <!-- 在插槽上绑定子组件的数据 -->
        <slot :userInfo="userInfo"/>
    </div>
    `
};

绑定在 元素上的特性被称为插槽 prop。现在在父级作用域中,我们可以给v-slot带一个值来定义我们提供的插槽 prop 的名字:

// 父组件
template: `
<div>
    <card>
        <template v-slot:default="userInfo">
            用户姓名: {{userInfo}}
        </template>
    </card>
</div>
`

// 输出:
// 用户姓名: { "userInfo": { "name": "宫鑫" } }

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

z-index不起作用的大坑

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

今天遇到的就是z-index不起作用的问题。一个后台小哥不知道抽什么疯,写元素覆盖偏不让用absolute,搞的我之后废了9牛二虎之力写了一下,问题描述是这样的,

 一对兄弟节点,insert和parent,parent有两个子节点subtop和subbottom,展现的结果是想让subtop在insert上面,subbottom在insert下面,

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style type="text/css">
        .insert{
            position: relative;
            z-index:100;
            background: green;
            width:300px;
            height:300px;
            top:100px;
        }
        .parent{
            /*position:relative;
            z-index: 1000;*/
            width:200px;
            height:200px;
            /*left:0;
            top:-50px;*/
            border:1px solid #eee;
        }
        .subbottom{
            position:relative;
            z-index: 50;
            width:200px;
            height:200px;
            background: red;
            top:-100px;
            left:0;
 
        }
        .subtop{
            position: relative;
            z-index:1100;
            width:100px;
            height:100px;
            left:0;
            top:0;
            background: blue;
        }
    </style>
</head>
<body>
    <div class="insert"></div>
    <div class="parent">
        <div class="subtop"></div>
        <div class="subbottom"></div>
    </div>
</body>
</html>

其实原理也很简单,就是利用了z-index的覆盖问题,在写的过程中我发现无论怎么改变,insert的z-index总是无效的,于是百度了一下z-index无效的情况,一共有三种:
1、父标签 position属性为relative;

2、问题标签无position属性(不包括static);

3、问题标签含有浮动(float)属性。

这样也很好理解为什么parent设置了position和z-index之后insert的z-index就会失效的问题了,他的解决办法有是三个:


1、position:relative改为position:absolute;

2、浮动元素添加position属性(如relative,absolute等);

3、去除浮动。

所以,去掉parent的position和z-index,达到了我想要的效果,如下图所示:

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、网站建设 平面设计服务

Vue+Electron下Vuex的Dispatch没有效果的解决方案

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

这个问题是解决基于 vue 和 electron 的开发中使用 vuex 的 dispatch 无效的问题,即解决了 Please, don't use direct commit's, use dispatch instead of this. 问题。

先允许我梳理一下目录结构,以便阅读的时候不会一头雾水,你到底说的这个文件是哪个……



其中 /src/main 是存放主配置文件的,/src/render 下面有 store、router、components 等。

components 下面就是很多 .vue 文件,router 下面就是一些路由配置的 js 文件和一些拦截器的 js。

关键是 store,store 下面有一个 index.js 的主配置文件 index.js,和一个 modules 文件夹。

index.js 里面写的是(记住这句话,后面会用到):

import Vue from 'vue'
import Vuex from 'vuex'

import { createPersistedState, createSharedMutations } from 'vuex-electron'

import modules from './modules'

Vue.use(Vuex)

export default new Vuex.Store({
  modules,
  plugins: [
    createPersistedState(),
    createSharedMutations()
  ],
  strict: process.env.NODE_ENV !== 'production'
})

而 modules/ 下面存放各个实体,例如上图中的 Auth.js 和 Counter.js,并通过 index.js 全部引入。

/**
 * The file enables `@/store/index.js` to import all vuex modules
 * in a one-shot manner. There should not be any reason to edit this file.
 */

const files = require.context('.', false, /\.js$/)
const modules = {}

files.keys().forEach(key => {
  if (key === './index.js') return
  modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default
})

export default modules


然后来看一个 vuex 的官方样例:

const state = {
  main: 0
}

const mutations = {
  DECREMENT_MAIN_COUNTER (state) {
    state.main--
  },
  INCREMENT_MAIN_COUNTER (state) {
    state.main++
  }
}

const actions = {
  someAsyncTask ({ commit }) {
    // do something async
    commit('INCREMENT_MAIN_COUNTER')
  }
}

export default {
  state,
  mutations,
  actions
}


之后很显然的,我想要在 Vue 的组件调用 INCREMENT_MAIN_COUNTER 对计数器加 1。

this.$store.commit('INCREMENT_MAIN_COUNTER');
// this.$store.commit('INCREMENT_MAIN_COUNTER', payload);
1
2
如果是一般的 vue,就 OK 了,但是,我遇到了报错,说,Please, don't use direct commit's, use dispatch instead of this.



那好吧,没事,不就是不然用 Commit,非要用 Dispatch 嘛,那我就写一个 Action,里面直接调用 Mutation,就像这个样子:

const actions = {
  JUST_INCREASE ({ commit }) {
    commit('INCREMENT_MAIN_COUNTER')
  }
}
1
2
3
4
5
然而奇怪的事情是,this.$store.dispatch('JUST_INCREASE') 并不能运行,没反应,计数器还是 0,不能赋值,就像是这个函数没有被执行一样。没有报错,没有任何异常,查也查不出什么问题。





网上的资料似乎也挺少。

折腾了很久,后来发现是 vuex-electron 里面一个插件的锅。

解决方法有两个。

方法一:

在 store/index.js 里面,就是上文特别强调了的那个文件,去掉 createSharedMutations 插件。

import Vue from 'vue'
import Vuex from 'vuex'

import { createPersistedState, createSharedMutations } from 'vuex-electron'

import modules from './modules'

Vue.use(Vuex)

export default new Vuex.Store({
  modules,
  plugins: [
    createPersistedState(),
    createSharedMutations() // 注释掉这一行
  ],
  strict: process.env.NODE_ENV !== 'production'
})


这是因为 vuex-electron 引入了一个用于多进程间共享 Vuex Store 的状态的插件。如果没有多进程交互的需求,完全可以不引入这个插件。

注释掉以后重启项目,用 this.$store.commit('XXX') 就可以使用了。

然而,如果需要多进程来处理怎么办?

方法二:

https://github.com/vue-electron/vuex-electron#installation

看第 3 条:

In case if you enabled createSharedMutations() plugin you need to create an instance of store in the main process. To do it just add this line into your main process (for example src/main.js):

import './path/to/your/store'
1
这种时候就不能用第一种方法来解决问题了。

好在文档也说了,加上一行导入。

找到 /src/main/index.js,在前面加上一句:

import '../renderer/store'
1


之后一切正常,可以使用 Dispatch 来进行操作了。



最后还有一个比较奇怪的问题:



在直接调用 state 的时候,这样写 this.$store.state.loginStatus 是不行的,会 undefined,必须写成 this.$store.state.Auth.loginStatus,就像是 this.$store.state.Counter.main 一样,似乎可以解释为,不同的模块不指定名字的话就找不到。

但是,在写 Dispatch 的时候又不需要指定名字了,直接 dispatch('changeLoginStatus') 就行了,不然难道不应该是也按照 dispatch('Auth/changeLoginStatus') 这样子来写嘛……
蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、网站建设 平面设计服务

Vue中使用Axios拦截器

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

需求是拦截前端的网络请求和相应。
废话不多说,直接上干货。



我用的是vue-cli3所以这个config文件是我自己创建的。

先介绍env.js

//根据不同的环境更改不同的baseUrl
let baseUrl = '';
 
//开发环境下
if (process.env.NODE_ENV == 'development') {
    baseUrl = '';
 
} else if (process.env.NODE_ENV == 'production') {
    baseUrl = '生产地址';
}
 
export {
    baseUrl,//导出baseUrl
}
在这里我首先设置了开发环境和生产环境的地址,并向外抛出。

在看一下axios.js

import {
    baseUrl, //引入baseUrl
} from "../config/env";
import axios from 'axios';
import qs from 'qs';
//引入vuex的js文件
import vuex from '../src/store/index';
 
// 创建 axios 实例
let service = axios.create({
    baseUrl: baseUrl,//请求前缀
    timeout: 20000,  // 请求超时时间
    crossDomain: true,//设置cross跨域
    withCredentials: true//设置cross跨域 并设置访问权限 允许跨域携带cookie信息
})
 
// 设置 post 默认 Content-Type
service.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
 
// 添加请求拦截器
service.interceptors.request.use(
 
    (config) => {
        // console.log()
        //下面的代码是如何在拦截器中调用vuex管理状态。
        //我这里主要是做了一个蒙层的遮盖
        // vuex.$store.commit('OPEN_LOADING');
 
 
        //判断请求方式是否为POST,进行转换格式
        config.method === 'post'
            ? config.data = qs.stringify({...config.data})
            : config.params = {...config.params};
        // 请求发送前进行处理
        return config
    },
    (error) => {
        // 请求错误处理
        return Promise.reject(error)
    }
)
 
// 添加响应拦截器
service.interceptors.response.use(
    (response) => {
        let { data } = response;
        return data
    },
    (error) => {
        let info = {},
            { status, statusText, data } = error.response
 
        if (!error.response) {
            info = {
                code: 5000,
                msg: 'Network Error'
            }
        } else {
            // 此处整理错误信息格式
            info = {
                code: status,
                data: data,
                msg: statusText
            }
        }
    }
)
 
/**
 * 向外抛出service
 */
export default service
最后将这个axios.js文件引入main.js中,并将引入的axios挂载到Vue实例上就ok了。

完美!如有不对的地方还请各位大佬指点,万分感谢。

踩过的坑:

    怎么在axios拦截器中使用vuex,首先我们要引入vuex的js文件,然后就可以用了,就这么简单。


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

Vue 全局变量,局部变量

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

全局组件和局部组件
* 1.先定义组件   Vue.component('组件名', { 组件模板对象 })
*   注意: 组件名不要使用原生的标签名, 若组件名定义时用的是驼峰命名法, 则调用时用中划线分割后小写
*                       例如: 组件-->mtText   使用时-->   <my-text></my-text>
* 2.配置组件的模板  注意: 组件的模板内容有且只有一个根元素
* 3.在视图层里调用 ,用双标签
* 4.组件是一个独立的作用域, 也可以看成一个特殊的vue实例, 可以有data, methods,computed等等
*   注意: 组件的data是函数, 函数中需要返回一个对象作为组件的data
全局组件案例

<body>
<div id="app">
    <my-component></my-component>
</div>
<script src="lib/vue-2.4.0.js"></script>
<script>
//全局组件
    Vue.component('myComponent',{
        //1.组件的内容/模板
        template: '<div><div>头部组件</div><h1 @click="fn">呵呵{{msg}}</h1></div>',
        data(){
            return {
                msg:'hello,组件'
            }
        },
        methods:{
            fn(){
                console.log(this.msg);
            }
        }
    })
    let vm = new Vue({
        el:"#app",
        data:{
        },
        methods:{

        },

    })
</script>
</body>
局部组件案例

<body>
<div id="app">
    <my-component></my-component>
    <my-test></my-test>
</div>
<template id="box1">
    <h1>haha</h1>
</template>
<template id="box2">
    <div>
        <ul>
            <li v-for="item in arr">
                {{ item }}
            </li>
        </ul>
    </div>
</template>
<script src="lib/vue-2.4.0.js"></script>
<script>
let vm = new Vue({
        el:"#app",
        data:{
        },
        methods:{

        },
        //局部子组件
        components:{
            // 组件名: {配置项}
            "myComponent":{
                template:'#box1',
                data(){
                    return {
                        msg:"哈哈"
                    }
                }
            },
            "myTest":{
                template:"#box2",
                data(){
                    return {
                        arr:[1,2,3,4]
                    }
                }
            }
        }
    })
</script>
</body>
组件切换:法一

<body>
<div id="app">
    <a href="" @click.prevent="flag=true">登录</a>
    <a href="" @click.prevent="flag=false">注册</a>
    <login v-if="flag"></login>
    <register v-else="flag"></register>
</div>
<script src="lib/vue-2.4.0.js"></script>
<script>
    Vue.component("login",{
        template:"<h1>登录组件</h1>"
    })
    Vue.component("register",{
        template:"<h1>注册组件</h1>"
    })
    let vm = new Vue({
        el:"#app",
        data:{
            flag: false
        },
        methods:{
        },
    })
</script>
</body>
组件切换:法二

 <style>
        .red{
            color:red;
        }
        .v-enter{
            opacity:0;
            transform: translateX(150px);
        }
        .v-leave-to{
            opacity:0;
            transform: translateX(-150px);
        }
        .v-enter-active,
        .v-leave-active{
            transition: all 0.5s;
            position: absolute;
        }
    </style>
</head>
<body>
<div id="app">
    <a href="" :class="{red: flag=='login'}" @click.prevent="flag='login'">登录</a>
    <a href="" :class="{red: flag=='register'}" @click.prevent="flag='register'">注册</a>
    <!--  vue提供了一个标签  component标签(理解为一个占位符), 用来展示对应名称的组件  :is属性设置指定的组件名  -->
    <transition>
        <component :is="flag"></component>
    </transition>
</div>
<script src="lib/vue-2.4.0.js"></script>
<script>
    Vue.component("login",{
        template:"<h1>登录组件</h1>"
    })
    Vue.component("register",{
        template:"<h1>注册组件</h1>"
    })
    let vm = new Vue({
        el:"#app",
        data:{
            flag: "login"
        },
        methods:{

        },
    })
</script>
</body>
父组件向子组件传值

<body>
<div id="app">
    <my-component :fromfather="father"></my-component>
</div>
<template id="box1">
    <h1 @click="change">
        {{ fromfather }}
        子组件的数据
    </h1>
</template>
<template id="grandSon">
    <h1>孙子组件的数据</h1>
</template>
<!--1.子组件不能访问父组件的数据
2. 解决办法: ①在引用子组件时, 通过属性绑定 v-bind方法, 把需要传递给子组件的数据以绑定的形式传过来
              ② 在子组件配置项里添加 props: ['传递过来的数据']-->
<script src="lib/vue-2.4.0.js"></script>
<script>
    let vm = new Vue({
        el:"#app",
        data:{
            father:'啊~~这是父组件的数据'
        },
        methods:{
        },
        //局部子组件
        components:{
            // 组件名: {配置项}
            "myComponent":{
                template:'#box1',
                data(){
                    return {
                        msg:"哈哈"
                    }
                },
                //在子组件配置项里添加 props: ['传递过来的数据']
                //注意: 组件中所有的props中的数据, 都是通过父组件传递给子组件的, props中的数据是只读, 无法修改
                props:['fromfather'],
                methods:{
                    change(){
                       // this.fromfather = "被修改了"
                    }
                },
                //局部子子组件
                components:{
                    'grandSon':{
                        template:'#grandSon'
                    }
                }
            }
        }
    })
</script>
</body>
蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

玩转javascript异步编程

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

一般知道,js脚步语言的执行环境是单线程的,就是它会等一个任务完成,才会进行第二个任务,然后一直向下进行,这样的执行环境简单,但是处理不了复杂的运用,当一个请求需要非常旧的时间的时候,下一个流程就会被搁浅,如果长时间得不到反馈,进程就这样的奔溃了。

为了解决这个硬性需求,Javascript语言提出了二种语言模式: 同步(Synchronous)和 异步 (Asynchronous)。

异步的几种常用方法

回调函数

订阅和发布模式

Promise

generator

async/await

回调函数方法

通过把一个函数(callback)作为参数传入另一个函数,当满足一定条件的时候,就执行callback函数。

用法:

640?wx_fmt=jpeg

通过回调函数的方式处理异步,是在异步早期的情况,其中jquery中的很多都是通过callback来实现回调的。但是这种模式代码编写比较耦合,不利于代码维护。

发布订阅模式

pub/sub模式是js设计模式中的一种,本身是借鉴于java的模式,但是在处理异步处理的时候非常有作用。通过一个信息中心EventCenter 来处理的监听(on)和触发(triggle)。

640?wx_fmt=jpeg

通过pub/sub模式,我们可以在信息中心清楚的看到有多少信号来源,方便的集中管理,更加方便于模块化的管理,但是如果整个项目都使用pub/sub模式的话,流程就变得不太清晰了,数据的得到和数据的处理分开,对于后期的维护也是一个很大的问题。

Promise

Promise构造函数成为承诺,它分为三种状态resolve, reject, pending ,一旦状态从pending改为其它2个状态之后,就不能修改了,就一个承诺一样。

Promise接收2个参数resolve , reject,分别表示成功后执行和失败后执行,可以通过实例的then()方法传递对于的函数。

640?wx_fmt=jpeg

这里看了之后,你可能会说,这个和异步处理有什么联系吗?你思考一下,当一个异步操作后,我们可以不去管它什么时候结束,什么时候出错,就像一个人承诺了,我只需要按照他的承诺去当这个事情已经被处理好了,是不是方便很多,下面直接上手一个例子。

640?wx_fmt=jpeg

我完全不用担心它里面怎么实现了,反正它已经承诺了会给我结果,我只需要通过then()方法去接受,我需要得到的值就可以了。

Promise.resolve(value) value可以是三种值

单个值

一个promsie实例

一个thenable对象

Promise.resolve(value).then((value) => {})

处理一个请求依赖另一个请求的情况

如果一个请求的结果是下一个请求的参数,如果我们使用原始的请求方法,就是出现一个像右的箭头的回调地狱。

一层层嵌套,非常的恐怖,不利于维护。那么通过prmise怎么处理回调地狱呢?

640?wx_fmt=jpeg

上面处理回调地狱是不是看着方便很多,代码也简单命令,依赖性也很强,后面我们会继续通过async/await继续简化。

处理多个请求并发的情况(不需要管服务器的返回顺序)

Promise.all(arr) 接受一个promise实例的数组,可以并发多个请求给服务器,但是并不能保证接受到的先后顺序,这个取决于服务器的处理速度。

640?wx_fmt=jpeg

处理多个请求并发,并且需要保证返回数据的顺序(运用场景比较少)

上面一个方法并不会保证请求返回的结果,按照你发送的顺序返回,如果我想把完整的响应的结果按照我

希望的顺序返回给我,那应该怎么办呢?

640?wx_fmt=jpeg

这样,会等待每一个请求完成后,并把得到的数据push到totalData中,就可以按照顺序得到我们想要的值了。当然使用async/await会更加的方便。之后我们会讲解。

generator构造器

generator是一个构造器,generator函数执行并不会执行函数体内部部分,而是返回一个构造器对象,通过构造器对象的next()方法调用函数主体,并且每当遇到yield都会暂停执行,并返回一个对象。

640?wx_fmt=jpeg

注意yield本身是不会反悔内容的,只是给构造器对象返回了内容,如果想yield表达式也返回内容,可以通过给下一个next()传递参数。

640?wx_fmt=jpeg

通过next()传递参数,我们可以做到值向内部传递,对于后面的异步处理很有帮助。

generator异步运用

利用构造器的暂停和继续的功能,我们可以很好的处理异步请求,得到数据后再进行其他内容。主要是运用yield表达式返回一个promise对象的原理。

640?wx_fmt=jpeg

这样我们就得到了接口请求的数据,相比于之前的promise函数的书写是不是要简单很多。和同步是一样的操作。

如果我们想内部对得到的数据进行进一步的处理呢?

640?wx_fmt=jpeg

简单的co模块处理generator多个函数请求

从上面我的调用方法就可以看出,利用Promise + generator的异步处理不断地通过then()方法处理数据。有没有一个方式是我可以直接运行一个函数,然后就可以得到我想要的值。 例如:

640?wx_fmt=jpeg

网上已经封装了很多的方法,例如常见的run库,co函数就是来处理这样的处理方式。但是当我们发送多个请求的时候,可能你会这样写:

640?wx_fmt=jpeg

这样写是会发送请求,但是并不是并发多个请求,而是等第一个请求p1之后,再进行第二个请求p2,在性能优化方面是不利的,也不符合我们的要求,怎么做到2个请求是独立的,并且我们还可以通过得到2个请求的结果后,进行其他请求。或许我们可以这样:

640?wx_fmt=jpeg

这样写是不是和我们之前写的Promise.all()很像?所以还可以改成这样的:

640?wx_fmt=jpeg

async/await异步处理

ES7出现了async/await进行异步的处理,使得异步操作就像同步代码一样简单,方便了使用,由于async/await内部封装了generator的 处理,所有就很少有人用generator来处理异步了,但是在异步的推动中generator起到了很大的作用。

await: 后面接受一个promise实例

**async: 返回一个promise对象 **

一个简单的异步请求

640?wx_fmt=jpeg

上面的例子是不是和generator中的异步请求很像?可以像同步一样的编写代码,但是相比generator,await后面加上promise后直接返回相应的数据,不像yield还需要从外部传入。

处理多个请求并发的情况(不需要管服务器的返回顺序)

用async/await处理多个请求并发,由于await后面需要添加Promise实例,是不是脑袋里面一下子就想到了一个Promise.all()

640?wx_fmt=jpeg

你可能会很好奇,为什么不需要像generator那样通过额外的函数来调用,因为async已经帮你想好了,内部已经调用了,是不是很爽?

处理多个请求并发,并且需要保证返回数据的顺序(运用场景比较少)

如果数据中没有相互的联系,但是又想一个个发送,可以这样

640?wx_fmt=jpeg


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

js获取video任意时间的画面截图

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

首先就是要把视频加载出来,然后使用canvas.getContext(‘2d’).drawImage(videoElement, 0, 0, canvas.width, canvas.height);获取到当前视频时间的截图,需要不同时间的video视频图,设置video的currentTime(单位秒),然后videoElement这个对象信息会实时更新。

如果是视频是在阿里云OSS上就更方便了,poster=“http://a-image-demo.oss-cn-qingdao.aliyuncs.com/demo.mp4?x-oss-process=video/snapshot,t_6000,m_fast”

如果是要获取上传本地视频预览图,可采用下面的方法,但有兼容性问题,目前测试移动端安卓机只有Chrome浏览器支持,微信和QQ浏览器都无法响应本地视频的canplay事件。

<div contenteditable="true" id="in-box" style="width:1000px;margin: 20px auto;"></div>
<div style="width:1000px;margin: 20px auto;">        
   <input type="file" name="" accept="video/*" id="upload-ipt">
   <div class="review" id="out-box"></div>
</div>

function getVideoImage() {
    var obj_file = document.getElementById("upload-ipt");
    var file = obj_file.files[0];
    var blob = new Blob([file]), // 文件转化成二进制文件
        url = URL.createObjectURL(blob); //转化成url
    if (file && /video/g.test(file.type)) {
        var $video = $('<div><video controls src="' + url + '"></video></div><div>&nbsp;</div>');
        //后面加一个空格div是为了解决在富文本中按Backspace时删除无反应的问题
        $('#in-box').html($video);
        var videoElement = $("video")[0];
        videoElement.addEventListener("canplay", function (_event) {
            var canvas = document.createElement("canvas");                    
            canvas.width = videoElement.videoWidth;
            canvas.height = videoElement.videoHeight;
            console.log(videoElement.videoWidth)
            canvas.getContext('2d').drawImage(videoElement, 0, 0, canvas.width, canvas.height);
            var img = document.createElement("img");
            img.src = canvas.toDataURL("image/png");
            $("#out-box").html(img);
            URL.revokeObjectURL(this.src); // 释放createObjectURL创建的对象
            console.log("loadedmetadata")
        });
    }else{
        alert("请上传一个视频文件!");
        obj_file.value = ""
    }
};
蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

javascript对数组和json数组的操作

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>javascript数组操作</title>
    <script type="application/javascript" src="lib/jquery.min.js"></script>
</head>
<body>
<h2>javascript操作数组</h2>
<input type="button" value="js数组" "jsArrays();">
<br>
<input type="button" value="json数组1" "jsonArrays();">
</body>
<script type="application/javascript">
//数组操作
    function jsArrays() {
    //创建一个javascript数组
        var a=new Array();
        a.push('a');
        a.push('b');
        a.push('c');
        //往数组添加三个元素
        alert(a);
        //利用indexof可以指出该元素在数组中所在位置
        alert('a index of a'+a.indexOf('a'));
        //利用jquery对数组进行便利
        $(a).each(function (index,row) {
            alert('index is '+index);
            alert('row is '+row);
        })
    }
    //json数组操作
    function jsonArrays() {
    //首先也是创建一个json数组
        var a=new Array();
        a.push({a:1});
        a.push({a:2});
        a.push({a:3});
        //同样的往数组添加三个元素
        //alert出的结果是[{object,object},{object,object},{object,object}]
        alert('a is '+a);
        //利用JSON的方法将json数组转换为字符串这时候alert的就是json字符串了
        alert(JSON.stringify(a));
        //直接获取json数组第一个元素的值,此时知道json的key是a
        alert(a[0].a);
        //遍历json数组第一个元素的key,这时候可以alert出的结果是a,同样的可以得出对应的value
        for(var key in a[1]){
            alert('key is '+key);
            alert('value is '+a[0][key]);
        }
        //用jquery对json数组进行遍历
        $(a).each(function (index,row) {
            for(var key in row){
                alert('each key is '+key);
                alert('each value is '+row[key]);
            }
        })
    }
</script>
</html>
蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

调试移动端网页工具Weinre使用整理

seo达人

一、Weinre 说明



Weinre的本意是Web Inspector Remote,它是一种远程调试工具。功能与Firebug、Webkit inspector类似,可以帮助我们即时更改页面元素、样式,调试JS等。



使用Weinre工具,Weinre的本意是Web Inspector Remote,它是一种远程调试工具:



1.它可以将远程的页面经过代理在PC上调试页面元素、样式,JS。



2.可以监听页面内部的Ajax请求等。



3.可以监听页面加载成功时候的Console控制台输出



官网首页:http://people.apache.org/~pmuellr/weinre/docs/latest/



Weinre的原理







三个端的含义:客户端(client):本地的WebInspector,远程调试客户端。服务端(agent):本地的HTTPServer,为目标页面与客户端建立通信。目标页面(target):被调试的页面,页面已嵌入weinre的远程js。



调试过程:



客户端将指令(请求DOM、执行js)post到代理服务端,目标页面定时(大概5s)从服务端get指令,然后将结果post回服务端,最终客户端定时从服务端get结果。



PS:由于Weinre的客户端是基于Web Inspector开发,而Web Inspector只兼容WebKit核心的浏览器,所以只能在Chrome/Safari浏览器打开Weinre客户端进行调试。





二、Weinre安装和使用



1.weinre是基于NodeJs,因此首先要安装NodeJs,然后使用npm命令安装weinre



npm -g install weinre

2.运行,启动weinre服务器,默认端口8080



node.exe node_modules\weinre\weinre --boundHost -all-

node.exe node_modules\weinre\weinre --boundHost  192.168.1.125 

在windows下,系统防火墙可能会弹出是否允许其访问网络的提示,点击充许即可。

3.从浏览器访问,http://localhost:8080,或者,http://192.168.1.125:8080,显示如下表示启动服务器监视成功











三、Weinre需要监听调试的Web页面配置处理



1.在所有页面引入js文件



2.特别说明,当前js文件的域名需要指定为本机的IP地址,因为在手机模拟器中无法访问电脑‘localhost’



















更多:



cordova-plugin-whitelist 协议白名单配置整理 



VS Code插件安装位置



Visual Studio Code插件之Atom One Dark Syntax Theme



相关参考文章:



http://blog.csdn.net/freshlover/article/details/42640253



http://www.cnblogs.com/diva/p/3995674.html

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

豆瓣API实践项目-前言-0

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

这是一个 app从获取获取数据 用于显示的经典实践项目,数据来源于 豆瓣官方公开的api接口:https://developers.douban.com/wiki/?title=movie_v2



先上图:

      

   





项目使用了如下第三方library:

下拉刷新:Android-PullToRefresh

网络数据加载:android-async-http

图片加载:universal-image-loader



后面的博客,会把项目的制作流程发出来

豆瓣API实践项目-前言-0(可下载源码): http://blog.csdn.net/mario_faker/article/details/79618210

豆瓣API实践项目-数据api接口-1:http://blog.csdn.net/mario_faker/article/details/79618235

豆瓣API实践项目-搭建项目基本框架-2:http://blog.csdn.net/mario_faker/article/details/79618245

豆瓣API实践项目-导入第三方library-3:http://blog.csdn.net/mario_faker/article/details/79618261

豆瓣API实践项目-单页细讲4: http://blog.csdn.net/mario_faker/article/details/79618272

豆瓣API实践项目-apk打包:http://blog.csdn.net/mario_faker/article/details/79618291





项目源代码下载地址:

http://download.csdn.net/download/mario_faker/10253201

或github:https://github.com/MarioFaker/DBMovie

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

日历

链接

blogger

蓝蓝 http://www.lanlanwork.com

存档