首页

React Native原生与JS层交互

seo达人

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

最近在对《React Native移动开发实战》一书进行部分修订和升级。在React Native开发中,免不了会涉及到原生代码与JS层的消息传递等问题,那么React Native究竟是如何实现与原生的互相操作的呢?

原生给React Native传参

原生给React Native传值

原生给JS传值,主要依靠属性,也就是通过initialProperties,这个RCTRootView的初始化函数的参数来完成。通过RCTRootView的初始化函数你可以将任意属性传递给React Native应用,参数initialProperties必须是NSDictionary的一个实例。RCTRootView有一个appProperties属性,修改这个属性,JS端会调用相应的渲染方法。

使用RCTRootView将React Natvie视图封装到原生组件中。RCTRootView是一个UIView容器,承载着React Native应用。同时它也提供了一个联通原生端和被托管端的接口。

例如有下面一段OC代码:

NSURL *jsCodeLocation;

  jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil]; NSArray *imageList = @[@"http://foo.com/bar1.png",
                         @"http://foo.com/bar2.png"]; NSDictionary *wjyprops = @{@"images" : imageList};

  RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                      moduleName:@"ReactNativeProject" initialProperties:wjyprops
                                                   launchOptions:launchOptions];
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

下面是JS层的处理:

import React, { Component } from 'react'; import {
  AppRegistry,
  View,
  Image,
} from 'react-native'; class ImageBrowserApp extends Component { renderImage(imgURI) { return (
      <Image source={{uri: imgURI}} />
    );
  }
  render() { return (
      <View>
        {this.props.images.map(this.renderImage)}
      </View>
    );
  }
}

AppRegistry.registerComponent('ImageBrowserApp', () => ImageBrowserApp);
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

不管OC中关于initialProperties的名字叫什么,在JS中都是this.props开头,然后接下来才是key名字。

{"rootTag":1,"initialProps":{"images":["http://foo.com/bar1.png","http://foo.com/bar2.png"]}}. 
    
  • 1

使用appProperties进行参数传递

RCTRootView同样提供了一个可读写的属性appProperties。在appProperties设置之后,React Native应用将会根据新的属性重新渲染。当然,只有在新属性和旧的属性有更改时更新才会被触发。

NSArray *imageList = @[@"http://foo.com/bar3.png", @"http://foo.com/bar4.png"]; rootView.appProperties = @{@"images" : imageList};
    
  • 1
  • 2
  • 3

可以随时更新属性,但是更新必须在主线程中进行,读取则可以在任何线程中进行。

React Native执行原生方法及回调

React Native执行原生方法

.h的文件代码:

#import <Foundation/Foundation.h> #import <RCTBridgeModule.h> @interface wjyTestManager : NSObject<RCTBridgeModule> @end
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

.m的文件代码:

#import "wjyTestManager.h" @implementation wjyTestManager RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(doSomething:(NSString *)aString withA:(NSString *)a)
{ NSLog(@"%@,%@",aString,a);
} @end
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

为了实现RCTBridgeModule协议,你的类需要包含RCT_EXPORT_MODULE()宏。这个宏也可以添加一个参数用来指定在Javascript中访问这个模块的名字。如果你不指定,默认就会使用这个Objective-C类的名字。

并且必须明确的声明要给Javascript导出的方法,否则React Native不会导出任何方法。OC中声明要给Javascript导出的方法,通过RCT_EXPORT_METHOD()宏来实现。

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Alert,
  TouchableHighlight,
} from 'react-native';

import {
  NativeModules,
  NativeAppEventEmitter
} from 'react-native'; var CalendarManager = NativeModules.wjyTestManager; class ReactNativeProject extends Component { render() { return (
          <TouchableHighlight onPress={()=>CalendarManager.doSomething('sdfsdf','sdfsdfs')}>
          <Text style={styles.text}
      >点击 </Text>
          </TouchableHighlight>

        );
      }
} const styles = StyleSheet.create({
text: {
  flex: 1,
  marginTop: 55,
  fontWeight: 'bold' },
});

AppRegistry.registerComponent('ReactNativeProject', () => ReactNativeProject);
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

要用到NativeModules则要引入相应的命名空间import { NativeModules } from ‘react-native’;然后再进行调用CalendarManager.doSomething(‘sdfsdf’,’sdfsdfs’);桥接到Javascript的方法返回值类型必须是void。React Native的桥接操作是异步的,所以要返回结果给Javascript,你必须通过回调或者触发事件来进行。

传参并回调

RCT_EXPORT_METHOD(testCallbackEvent:(NSDictionary *)dictionary callback:(RCTResponseSenderBlock)callback)
{ NSLog(@"当前名字为:%@",dictionary); NSArray *events=@[@"callback ", @"test ", @" array"];
  callback(@[[NSNull null],events]);
}
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

说明:第一个参数代表从JavaScript传过来的数据,第二个参数是回调方法; 
JS层代码:

import {
  NativeModules,
  NativeAppEventEmitter
} from 'react-native'; var CalendarManager = NativeModules.wjyTestManager; class ReactNativeProject extends Component { render() { return (
          <TouchableHighlight onPress={()=>{CalendarManager.testCallbackEvent(
             {'name':'good','description':'http://www.lcode.org'},
             (error,events)=>{ if(error){
                   console.error(error);
                 }else{
                   this.setState({events:events});
                 }
           })}}
         >
          <Text style={styles.text}
      >点击 </Text>
          </TouchableHighlight>

        );
      }
}
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

参数类型说明

RCT_EXPORT_METHOD 支持所有标准JSON类型,包括:

  • string (NSString)
  • number (NSInteger, float, double, CGFloat, NSNumber)
  • boolean (BOOL, NSNumber)
  • array (NSArray) 包含本列表中任意类型
  • object (NSDictionary) 包含string类型的键和本列表中任意类型的值
  • function (RCTResponseSenderBlock)

除此以外,任何RCTConvert类支持的的类型也都可以使用(参见RCTConvert了解更多信息)。RCTConvert还提供了一系列辅助函数,用来接收一个JSON值并转换到原生Objective-C类型或类。例如:

#import "RCTConvert.h" #import "RCTBridge.h" #import "RCTEventDispatcher.h" //  对外提供调用方法,为了演示事件传入属性字段 RCT_EXPORT_METHOD(testDictionaryEvent:(NSString *)name details:(NSDictionary *) dictionary)
{ NSString *location = [RCTConvert NSString:dictionary[@"thing"]]; NSDate *time = [RCTConvert NSDate:dictionary[@"time"]]; NSString *description=[RCTConvert NSString:dictionary[@"description"]]; NSString *info = [NSString stringWithFormat:@"Test: %@\nFor: %@\nTestTime: %@\nDescription: %@",name,location,time,description]; NSLog(@"%@", info);
}
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

iOS原生访问React Native

如果需要从iOS原生方法发送数据到JavaScript中,那么使用eventDispatcher。例如:

#import "RCTBridge.h" #import "RCTEventDispatcher.h" @implementation CalendarManager @synthesize bridge = _bridge; //  进行设置发送事件通知给JavaScript端 - (void)calendarEventReminderReceived:(NSNotification *)notification
{ NSString *name = [notification userInfo][@"name"];
    [self.bridge.eventDispatcher sendAppEventWithName:@"EventReminder" body:@{@"name": name}];
} @end
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在JavaScript中可以这样订阅事件,通常需要在componentWillUnmount函数中取消事件的订阅。

import { NativeAppEventEmitter } from 'react-native';

var subscription = NativeAppEventEmitter.addListener( 'EventReminder',
  (reminder) => console.log(reminder.name)
); ... // 千万不要忘记忘记取消订阅, 通常在componentWillUnmount函数中实现。
subscription.remove();
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

用NativeAppEventEmitter.addListener中注册一个通知,之后再OC中通过bridge.eventDispatcher sendAppEventWithName发送一个通知,这样就形成了调用关系。

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

js学习中的总结——几种继承模式

seo达人

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

     js中构造函数的几种继承模式浅析

一、原型链模式继承

    利用原型让一个引用类型继承另一个引用类型的属性和方法 。

    用的最多。

    缺点:不可传参,不可多继承。


        
  1. function People(name, age) {//添加公有属性
  2. name = name || 'xiaolan';
  3. age = age || 18;
  4. this.name = name;
  5. this.age = age;
  6. }//创建一个名为People的类
  7. People.prototype.eat = function() {//添加私有属性
  8. console.log(this.name + '贼能吃');
  9. }
  10. function Cat(color) {//创建一个名为Cat的类
  11. this.color = color;
  12. }
  13. Cat.prototype = new People('小叮当', 200);//实例化一个People类,并赋值给Cat类的原型链
  14. var cat = new Cat('蓝白色')
  15. console.log(cat.name)//'小叮当'
  16. cat.eat();//'小叮当贼能吃'

二、混合模式继承

    用call的方法只能继承私有属性,所以再加一遍一遍原型链模式继承,原型链模式继承又把私有属性和公有属性都继承了一遍。


        
  1. function People(name, age) { //创建一个父级People类
  2. name = name || 'xiaolan';
  3. age = age || 18;
  4. this.name = name;
  5. this.age = age;
  6. }
  7. People.prototype.eat = function() {
  8. console.log(this.name + '贼能吃');
  9. }
  10. function Cat(color, name, age) {
  11. this.color = color;
  12. People.call(this, name, age); //通过call的形式继承
  13. //通过call(this),将People的指向改为Cat的实例
  14. }
  15. var cat = new Cat('蓝白色', '小叮当', 1);
  16. console.log(cat.name);//'小叮当'
  17. cat.eat();//报错,
  18. //继承不了公有属性,所以cat.eat()会报错;

为了继承公有属性,用原型链模式在把公有属性和方法继承过来,


        
  1. function People(name, age) { //创建一个父级People类
  2. name = name || 'xiaolan';
  3. age = age || 18;
  4. this.name = name;
  5. this.age = age;
  6. }
  7. People.prototype.eat = function() {
  8. console.log(this.name + '贼能吃');
  9. }
  10. function Cat(color, name, age) {
  11. this.color = color;
  12. People.call(this, name, age); //通过call的形式继承
  13. //通过call(this),将People的指向改为Cat的实例
  14. }
  15. Cat.prototype = new People()
  16. var cat = new Cat('蓝白色', '小叮当', 200)
  17. console.log(cat)
  18. console.log(cat.name); //'小叮当',在原型链继承的时候,就近原则,cat.name 先找到'小叮当',就不往下找了
  19. cat.eat(); //'小叮当贼能吃'

三、拷贝继承

    优点:可以多继承,可传参;

    缺点:浪费资源,不能判断父级;


        
  1. function People(name, age) { //创建一个父级People类
  2. name = name || 'xiaolan';
  3. age = age || 18;
  4. this.name = name;
  5. this.age = age;
  6. }
  7. People.prototype.eat = function() {
  8. console.log(this.name + '贼能吃');
  9. }
  10. function Cat(color, name, age) {
  11. this.color = color;
  12. var people = new People(name, age) //实例化一个People类
  13. for (let i in people) {
  14. this[i] = people[i]; //将people中的可枚举属性和方法遍历并附给Cat类,公有属性和私有属性都是可枚举属性;
  15. }
  16. }
  17. var cat = new Cat('蓝白色', '小叮当', 2);
  18. console.log(cat.name); //小叮当
  19. cat.eat(); //小叮当贼能吃

四、寄生组合方式继承

    优点:私有属性和公有属性都单独继承,可以传参;

    私有属性可以多继承,公有属性不可多继承;


        
  1. function People(name, age) {
  2. name = name || 'xiaolan';
  3. age = age || 18;
  4. this.name = name;
  5. this.age = age;
  6. }
  7. People.prototype.eat = function() {
  8. console.log(this.name + '贼能吃');
  9. }
  10. function Cat(color, name, age) {
  11. this.color = color;
  12. People.call(this, name, age) //用call的形式把私有属性继承过来
  13. }
  14. function Fn() {} //创建一个中间构造函数,用来接收People的公有属性,为了防止创建实例Cat实例是影响原来的people构造函数
  15. Fn.prototype = People.prototype;
  16. Cat.prototype = new Fn(); //将中间构造函数Fn继承people的公有属性传给Cat的原型链
  17. Cat.prototype.constructor = Cat; //由于上一步重置了Cat原型链的constructor属性,所以要重新给赋回来;
  18. var cat = new Cat('蓝白色', '小叮当', 3);
  19. console.log(cat.name); //'小叮当'
  20. cat.eat() //'小叮当贼能吃


注:若有不严谨与错误的地方,请多指教!






  1. 这里写图片描述



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


vue在ie9中的兼容问题

seo达人

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

问题总结  https://github.com/vuejs-templates/webpack/issues/260

  1. 首先npm install --save babel-polyfill

  2. 然后在main.js中的最前面引入babel-polyfill

    import 'babel-polyfill'

  3. 在index.html 加入以下代码(非必须)

    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

  4. 在config中的webpack.base.conf.js中,修改编译配置


    
  1. entry:{
  2. app:['babel-polyfill','./src/main.js']
  3. }

当然,如果你只用到了 axios 对 promise进行兼容,可以只用 es6-promise

npm install es6-promise --save

在 main.js 中的最前面 引入

import 'es6-promise/auto' 
  • 以上配置,ie9兼容就完成了

那么,就有一个问题了,build之后的dist文件只有放在服务器上才能查看,但本地如何查看呢,参考一下配置

  1. 修改config文件夹中的index.js文件,将build对象中的打包路径,'/‘改为'./',由绝对路径改为相对路径,建议将sourceMap改为false,编译的时候会快一点

    build: { assetsPublicPath: './', productionSourceMap: false, },

  2. 修改完之后,重新 npm run build ,得到新的dist文件夹

  3. 然后进入dist文件夹

    cd dist

  4. 全局安装简易node服务器

    npm install http-server -g

  5. 启动简易node服务器

    http-server

  6. 出现如下图所示,就代表你的服务器启动成功了,那你也能在5000端口查看编译打包后的项目了,可以在ie浏览器中直接测试了

    这里写图片描述

  7. IE在处理日期的时候,不支持-支持/的日期方式 如 2017-01-01应该 


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


ES6新特性Promise异步调用

seo达人

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

Promise 的含义

Promise 是异步编程的一种解决方案,比传统的解决方案–回调函数和事件--更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了语法,原生提供了Promise

所谓Promise ,简单说就是一个容器,里面保存着某个未来才回结束的事件(通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。 
Promise 对象的状态不受外界影响

三种状态:

  • pending:进行中
  • fulfilled :已经成功
  • rejected 已经失败

状态改变: 
Promise对象的状态改变,只有两种可能:

  • 从pending变为fulfilled
  • 从pending变为rejected。

这两种情况只要发生,状态就凝固了,不会再变了,这时就称为resolved(已定型

基本用法

ES6规定,Promise对象是一个构造函数,用来生成Promise实例


    
  1. const promist = new Promise(function(resolve,reject){
  2. if(/*异步操作成功*/){
  3. resolve(value);
  4. }else{
  5. reject(error);
  6. }
  7. })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去; 
reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

Promise的源码分析:

1.回调地狱

曾几何时,我们的代码是这样的,为了拿到回调的结果,不得不callback hell,这种环环相扣的代码可以说是相当恶心了


            
  1. let fs = require('fs')
  2. fs.readFile('./a.txt','utf8',function(err,data){
  3. fs.readFile(data,'utf8',function(err,data){
  4. fs.readFile(data,'utf8',function(err,data){
  5. console.log(data)
  6. })
  7. })
  8. })

终于,我们的盖世英雄出现了,他身披金甲圣衣、驾着七彩祥云。好吧打岔儿了,没错他就是我们的Promise,那让我们来看看用了Promise之后,上面的代码会变成什么样吧


            
  1. let fs = require('fs')
  2. function read(url){
  3. return new Promise((resolve,reject)=>{
  4. fs.readFile(url,'utf8',function(error,data){
  5. error && reject(error)
  6. resolve(data)
  7. })
  8. })
  9. }
  10. read('./a.txt').then(data=>{
  11. return read(data)
  12. }).then(data=>{
  13. return read(data)
  14. }).then(data=>{
  15. console.log(data)
  16. })

2.重点开始,小眼睛都看过来

2.1 Promise/A+

首先我们要知道自己手写一个Promise,应该怎么去写,谁来告诉我们怎么写,需要遵循什么样的规则。当然这些你都不用担心,其实业界都是通过一个规则指标来生产Promise的。让我们来看看是什么东西。传送门☞Promise/A+

2.2 constructor

我们先声明一个类,叫做Promise,里面是构造函数。如果es6还有问题的可以去阮大大的博客上学习一下(传送门☞es6


            
  1. class Promise{
  2. constructor(executor){
  3. //控制状态,使用了一次之后,接下来的都不被使用
  4. this.status = 'pendding'
  5. this.value = undefined
  6. this.reason = undefined
  7. //定义resolve函数
  8. let resolve = (data)=>{
  9. //这里pendding,主要是为了防止executor中调用了两次resovle或reject方法,而我们只调用一次
  10. if(this.status==='pendding'){
  11. this.status = 'resolve'
  12. this.value = data
  13. }
  14. }
  15. //定义reject函数
  16. let reject = (data)=>{
  17. if(this.status==='pendding'){
  18. this.status = 'reject'
  19. this.reason = data
  20. }
  21. }
  22. //executor方法可能会抛出异常,需要捕获
  23. try{
  24. //将resolve和reject函数给使用者
  25. executor(resolve,reject)
  26. }catch(e){
  27. //如果在函数中抛出异常则将它注入reject中
  28. reject(e)
  29. }
  30. }
  31. }

那么接下来我会分析上面代码的作用,原理

  • executor:这是实例Promise对象时在构造器中传入的参数,一般是一个function(resolve,reject){}
  • status:``Promise的状态,一开始是默认的pendding状态,每当调用道resolve和reject方法时,就会改变其值,在后面的then方法中会用到
  • value:resolve回调成功后,调用resolve方法里面的参数值
  • reason:reject回调成功后,调用reject方法里面的参数值
  • resolve:声明resolve方法在构造器内,通过传入的executor方法传入其中,用以给使用者回调
  • reject:声明reject方法在构造器内,通过传入的executor方法传入其中,用以给使用者回调

2.3 then

then方法是Promise中最为重要的方法,他的用法大家都应该已经知道,就是将Promise中的resolve或者reject的结果拿到,那么我们就能知道这里的then方法需要两个参数,成功回调和失败回调,上代码!


            
  1. then(onFufilled,onRejected){
  2. if(this.status === 'resolve'){
  3. onFufilled(this.value)
  4. }
  5. if(this.status === 'reject'){
  6. onRejected(this.reason)
  7. }
  8. }

这里主要做了将构造器中resolve和reject的结果传入onFufilledonRejected中,注意这两个是使用者传入的参数,是个方法。所以你以为这么简单就完了?要想更Swag的应对各种场景,我们必须得再完善。继续往下走!

3.异步的Promise

之前我们只是处理了同步情况下的Promise,简而言之所有操作都没有异步的成分在内。那么如果是异步该怎么办?

3.1 callback!!!!

最早处理异步的方法就是callback,就相当于我让你帮我扫地,我会在给你发起任务时给你一个手机,之后我做自己的事情去,不用等你,等你扫完地就会打手机给我,诶,我就知道了地扫完了。这个手机就是callback,回调函数。

首先我们需要改一下构造器里的代码,分别添加两个回调函数的数组,分别对应成功回调和失败回调。他们的作用是当成功执行resolve或reject时,执行callback。


            
  1. //存放成功回调的函数
  2. this.onResolvedCallbacks = []
  3. //存放失败回调的函数
  4. this.onRejectedCallbacks = []
  5. let resolve = (data)=>{
  6. if(this.status==='pendding'){
  7. this.status = 'resolve'
  8. this.value = data
  9. //监听回调函数
  10. this.onResolvedCallbacks.forEach(fn=>fn())
  11. }
  12. }
  13. let reject = (data)=>{
  14. if(this.status==='pendding'){
  15. this.status = 'reject'
  16. this.reason = data
  17. this.onRejectedCallbacks.forEach(fn=>fn())
  18. }
  19. }

然后是then需要多加一个状态判断,当Promise中是异步操作时,需要在我们之前定义的回调函数数组中添加一个回调函数。


            
  1. if(this.status === 'pendding'){
  2. this.onResolvedCallbacks.push(()=>{
  3. // to do....
  4. let x = onFufilled(this.value)
  5. resolvePromise(promise2,x,resolve,reject)
  6. })
  7. this.onRejectedCallbacks.push(()=>{
  8. let x = onRejected(this.reason)
  9. resolvePromise(promise2,x,resolve,reject)
  10. })
  11. }

ok!大功告成,异步已经解决了

3.2 resolvePromise

这也是Promise中的重头戏,我来介绍一下,我们在用Promise的时候可能会发现,当then函数中return了一个值,我们可以继续then下去,不过是什么值,都能在下一个then中获取,还有,当我们不在then中放入参数,例:promise.then().then(),那么其后面的then依旧可以得到之前then返回的值,可能你现在想很迷惑。让我来解开你心中的忧愁,follow me


            
  1. then(onFufilled,onRejected){
  2. //解决onFufilled,onRejected没有传值的问题
  3. onFufilled = typeof onFufilled === 'function'?onFufilled:y=>y
  4. //因为错误的值要让后面访问到,所以这里也要跑出个错误,不然会在之后then的resolve中捕获
  5. onRejected = typeof onRejected === 'function'?onRejected:err=>{ throw err ;}
  6. //声明一个promise对象
  7. let promise2
  8. if(this.status === 'resolve'){
  9. //因为在.then之后又是一个promise对象,所以这里肯定要返回一个promise对象
  10. promise2 = new Promise((resolve,reject)=>{
  11. setTimeout(()=>{
  12. //因为穿透值的缘故,在默认的跑出一个error后,不能再用下一个的reject来接受,只能通过try,catch
  13. try{
  14. //因为有的时候需要判断then中的方法是否返回一个promise对象,所以需要判断
  15. //如果返回值为promise对象,则需要取出结果当作promise2的resolve结果
  16. //如果不是,直接作为promise2的resolve结果
  17. let x = onFufilled(this.value)
  18. //抽离出一个公共方法来判断他们是否为promise对象
  19. resolvePromise(promise2,x,resolve,reject)
  20. }catch(e){
  21. reject(e)
  22. }
  23. },0)
  24. })
  25. }
  26. if(this.status === 'reject'){
  27. promise2 = new Promise((resolve,reject)=>{
  28. setTimeout(()=>{
  29. try{
  30. let x = onRejected(this.reason)
  31. resolvePromise(promise2,x,resolve,reject)
  32. }catch(e){
  33. reject(e)
  34. }
  35. },0)
  36. })
  37. }
  38. if(this.status === 'pendding'){
  39. promise2 = new Promise((resolve,reject)=>{
  40. this.onResolvedCallbacks.push(()=>{
  41. // to do....
  42. setTimeout(()=>{
  43. try{
  44. let x = onFufilled(this.value)
  45. resolvePromise(promise2,x,resolve,reject)
  46. }catch(e){
  47. reject(e)
  48. }
  49. },0)
  50. })
  51. this.onRejectedCallbacks.push(()=>{
  52. setTimeout(()=>{
  53. try{
  54. let x = onRejected(this.reason)
  55. resolvePromise(promise2,x,resolve,reject)
  56. }catch(e){
  57. reject(e)
  58. }
  59. })
  60. })
  61. })
  62. }
  63. return promise2
  64. }

一下子多了很多方法,不用怕,我会一一解释

  1. 返回Promise?:首先我们要注意的一点是,then有返回值,then了之后还能在then,那就说明之前的then返回的必然是个Promise
  2. 为什么外面要包一层setTimeout?:因为Promise本身是一个异步方法,属于微任务一列,必须得在执行栈执行完了在去取他的值,所以所有的返回值都得包一层异步setTimeout。
  3. 为什么开头有两个判断?:这就是之前想要解决的如果then函数中的参数不是函数,那么我们需要做处理。如果onFufilled不是函数,就需要自定义个函数用来返回之前resolve的值,如果onRejected不是函数,自定义个函数抛出异常。这里会有个小坑,如果这里不抛出异常,会在下一个then的onFufilled中拿到值。又因为这里抛出了异常所以所有的onFufilled或者onRejected都需要try/catch,这也是Promise/A+的规范。当然本人觉得成功的回调不需要抛出异常也可以,大家可以仔细想想。
  4. resolvePromise是什么?:这其实是官方Promise/A+的需求。因为你的then可以返回任何职,当然包括Promise对象,而如果是Promise对象,我们就需要将他拆解,直到它不是一个Promise对象,取其中的值。

那就让我们来看看这个resolvePromise到底长啥样。


            
  1. function resolvePromise(promise2,x,resolve,reject){
  2. //判断x和promise2之间的关系
  3. //因为promise2是上一个promise.then后的返回结果,所以如果相同,会导致下面的.then会是同一个promise2,一直都是,没有尽头
  4. if(x === promise2){//相当于promise.then之后return了自己,因为then会等待return后的promise,导致自己等待自己,一直处于等待
  5. return reject(new TypeError('循环引用'))
  6. }
  7. //如果x不是null,是对象或者方法
  8. if(x !== null && (typeof x === 'object' || typeof x === 'function')){
  9. //为了判断resolve过的就不用再reject了,(比如有reject和resolve的时候)
  10. let called
  11. try{//防止then出现异常,Object.defineProperty
  12. let then = x.then//取x的then方法可能会取到{then:{}},并没有执行
  13. if(typeof then === 'function'){
  14. //我们就认为他是promise,call他,因为then方法中的this来自自己的promise对象
  15. then.call(x,y=>{//第一个参数是将x这个promise方法作为this指向,后两个参数分别为成功失败回调
  16. if(called) return;
  17. called = true
  18. //因为可能promise中还有promise,所以需要递归
  19. resolvePromise(promise2,y,resolve,reject)
  20. },err=>{
  21. if(called) return;
  22. called = true
  23. //一次错误就直接返回
  24. reject(err)
  25. })
  26. }else{
  27. //如果是个普通对象就直接返回resolve作为结果
  28. resolve(x)
  29. }
  30. }catch(e){
  31. if(called) return;
  32. called = true
  33. reject(e)
  34. }
  35. }else{
  36. //这里返回的是非函数,非对象的值,就直接放在promise2的resolve中作为结果
  37. resolve(x)
  38. }
  39. }

它的作用是用来将onFufilled的返回值进行判断取值处理,把最后获得的值放入最外面那层的Promise的resolve函数中。

  1. 参数promise2(then函数返回的Promise对象),x(onFufilled函数的返回值),resolve、reject(最外层的Promise上的resolve和reject)。
  2. 为什么要在一开始判断promise2x?:首先在Promise/A+中写了需要判断这两者如果相等,需要抛出异常,我就来解释一下为什么,如果这两者相等,我们可以看下下面的例子,第一次p2是p1.then出来的结果是个Promise对象,这个Promise对象在被创建的时候调用了resolvePromise(promise2,x,resolve,reject)函数,又因为x等于其本身,是个Promise,就需要then方法递归它,直到他不是Promise对象,但是x(p2)的结果还在等待,他却想执行自己的then方法,就会导致等待。

            
  1. let p1 = new Promise((resolve,reject)=>{
  2. resolve()
  3. })
  4. let p2 = p1.then(d=>{
  5. return p2
  6. })
  1. called是用来干嘛的?:called变量主要是用来判断如果resolvePromise函数已经resolve或者reject了,那就不需要在执行下面的resolce或者reject。
  2. 为什么取then这个属性?:因为我们需要去判断x是否为Promise,then属性如果为普通值,就直接resolve掉,如果是个function,就是Promise对象,之后我们就需要将这个x的then方法进行执行,用call的原因是因为then方法里面this指向的问题。
  3. 为什么要递归去调用resolvePromise函数?:相信细心的人已经发现了,我这里使用了递归调用法,首先这是Promise/A+中要求的,其次是业务场景的需求,当我们碰到那种Promise的resolve里的Promise的resolve里又包了一个Promise的话,就需要递归取值,直到x不是Promise对象。

4.完善Promise

我们现在已经基本完成了Promise的then方法,那么现在我们需要看看他的其他方法。

4.1 catch

相信大家都知道catch这个方法是用来捕获Promise中的reject的值,也就是相当于then方法中的onRejected回调函数,那么问题就解决了。我们来看代码。


            
  1. //catch方法
  2. catch(onRejected){
  3. return this.then(null,onRejected)
  4. }

该方法是挂在Promise原型上的方法。当我们调用catch传callback的时候,就相当于是调用了then方法。

4.2 resolve/reject

大家一定都看到过Promise.resolve()、Promise.reject()这两种用法,它们的作用其实就是返回一个Promise对象,我们来实现一下。


            
  1. //resolve方法
  2. Promise.resolve = function(val){
  3. return new Promise((resolve,reject)=>{
  4. resolve(val)
  5. })
  6. }
  7. //reject方法
  8. Promise.reject = function(val){
  9. return new Promise((resolve,reject)=>{
  10. reject(val)
  11. })
  12. }

这两个方法是直接可以通过class调用的,原理就是返回一个内部是resolve或reject的Promise对象。

4.3 all

all方法可以说是Promise中很常用的方法了,它的作用就是将一个数组的Promise对象放在其中,当全部resolve的时候就会执行then方法,当有一个reject的时候就会执行catch,并且他们的结果也是按着数组中的顺序来排放的,那么我们来实现一下。


            
  1. //all方法(获取所有的promise,都执行then,把结果放到数组,一起返回)
  2. Promise.all = function(promises){
  3. let arr = []
  4. let i = 0
  5. function processData(index,data){
  6. arr[index] = data
  7. i++
  8. if(i == promises.length){
  9. resolve(arr)
  10. }
  11. }
  12. return new Promise((resolve,reject)=>{
  13. for(let i=0;i<promises.length;i++){
  14. promises[i].then(data=>{
  15. processData(i,data)
  16. },reject)
  17. }
  18. })
  19. }

其原理就是将参数中的数组取出遍历,每当执行成功都会执行processData方法,processData方法就是用来记录每个Promise的值和它对应的下标,当执行的次数等于数组长度时就会执行resolve,把arr的值给then。这里会有一个坑,如果你是通过arr数组的长度来判断他是否应该resolve的话就会出错,为什么呢?因为js数组的特性,导致如果先出来的是1位置上的值进arr,那么0位置上也会多一个空的值,所以不合理。

4.4 race

race方法虽然不常用,但是在Promise方法中也是一个能用得上的方法,它的作用是将一个Promise数组放入race中,哪个先执行完,race就直接执行完,并从then中取值。我们来实现一下吧。


            
  1. //race方法
  2. Promise.race = function(promises){
  3. return new Promise((resolve,reject)=>{
  4. for(let i=0;i<promises.length;i++){
  5. promises[i].then(resolve,reject)
  6. }
  7. })
  8. }

原理大家应该看懂了,很简单,就是遍历数组执行Promise,如果有一个Promise执行成功就resolve。

Promise语法糖 deferred

语法糖这三个字大家一定很熟悉,作为一个很Swag的前端工程师,对async/await这对兄弟肯定很熟悉,没错他们就是generator的语法糖。而我们这里要讲的语法糖是Promise的。


            
  1. //promise语法糖 也用来测试
  2. Promise.deferred = Promise.defer = function(){
  3. let dfd = {}
  4. dfd.promise = new Promise((resolve,reject)=>{
  5. dfd.resolve = resolve
  6. dfd.reject = reject
  7. })
  8. return dfd
  9. }

什么作用呢?看下面代码你就知道了


            
  1. let fs = require('fs')
  2. let Promise = require('./promises')
  3. //Promise上的语法糖,为了防止嵌套,方便调用
  4. //坏处 错误处理不方便
  5. function read(){
  6. let defer = Promise.defer()
  7. fs.readFile('./1.txt','utf8',(err,data)=>{
  8. if(err)defer.reject(err)
  9. defer.resolve(data)
  10. })
  11. return defer.Promise
  12. }

没错,我们可以方便的去调用他语法糖defer中的Promise对象。那么它还有没有另外的方法呢?答案是有的。我们需要在全局上安装promises-aplus-tests插件npm i promises-aplus-tests -g,再输入promises-aplus-tests [js文件名] 即可验证你的Promise的规范。


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


么去控制浏览器对资源文件的处理行为

seo达人

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

通常当用户打开一个资源的url,如果浏览器支持这个格式的文件的情况下,浏览器会尝试去再页面里展示它而不是直接下载。例如一张图片(jpg, png, gif等),几乎所有浏览器都会去将图片在浏览器里面展示。


对于压缩格式的文件(zip, tar, gzip等)浏览器总是会直接去下载它们,另外一些格式的文件,根据浏览器的不同也会有差异的处理方法,例如Microsoft Word文件(doc, docx)在ie浏览器下通常会在浏览器中展示,但是其他浏览器几乎都会直接下载它,同样的对于PDF文件chrome有自己的pdf 转换器它会尝试去在浏览器上展示该文件。

强制下载文件

对于浏览器这种行为,一般情况下是可以接受的,因为用户可以在浏览器显示文件后将文件保存到电脑中,但是一些情况下用户可能希望文件直接被下载而不是在浏览器中被打开,比如有时候用户想去下载一个歌曲,但是浏览器可能回去播放该音频。那么怎么让浏览器强制去下载文件要怎么做呢

a标签的download属性

html5中 a 标签新增了 download 属性,该属性指示浏览器下载url的内容而不是导航到url,因此如果配置了此属性用户会直接下载url的内容。作为开发如果想直接触发该事件我们可以直接用代码模拟a标签和点击事件


    
  1. const link = document.createElement('a');
  2. link.addEventListener('click', function() {
  3. link.download = xxx;
  4. link.href = xxx;
  5. });
  6. const e = document.createEvent('MouseEvents');
  7. e.initEvent('click', false, false);
  8. link.dispatchEvent(e);
  • download属性只在同域时候有效,当跨域请求时候该属性将会被忽略。
  • 当前并非所以浏览器都支持该属性,需要浏览器考虑兼容性。

改变资源格式

浏览器会根据资源类型去判断是否支持,如果支持时会尝试去在页面上展示该资源。浏览器判断资源类型是根据返回头Content-Type的值,因此一方面我们在服务端可以设置返回头字段为文件流'Content-Type': 'application/octet-stream',或者根据一些具体资源直接压缩后传输,浏览器不能分析zip之类的压缩文件所以会直接去下载它们。

配置Content-Disposition

在HTTP场景中,Content-Disposition 消息头指示回复的内容该以何种形式展示,是以内联的形式(即网页或者页面的一部分),还是以附件的形式下载并保存到本地。

  • inline 默认参数表示消息体会以页面的一部分或者整个页面的形式展示。
  • attachment 消息体应该被下载到本地,将参数filename的值预填为下载后的文件名

因此当我们希望该资源被直接下载时候,我们可以设置返回头Content-Disposition的值为attachment


    
  1. //example
  2. Content-Disposition: attachment; filename="fname.ext"

这里设置名称时候,要注意下filename的编码格式。

用户自己在浏览器设置

浏览器既然定义了该行为,根据浏览器的不同用户可能在设置页面去配置某些格式的文件是否希望浏览器去展示该文件。一些有争议的情况下,你也可以提示用户自己根据需求去设置这些参数。


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


Javascrpit之打字机效果

seo达人

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

今天来看看怎么实现炫酷的打字机效果。即把一段话一个字一个字的显示出来。

效果图:

实现思路:

首先规定好显示字数的速度即settimeout执行间隔用来控制每个字之间输出速度。再把判断段落的总字数,循环段落总字数来实现一个字一个字的输出。

js代码:


    
  1. var theNewsNum;
  2. var theAddNum;
  3. var totalNum;
  4. var CurrentPosion=0;
  5. var theCurrentNews;
  6. var theCurrentLength;
  7. var theNewsText;
  8. var theTargetLink;
  9. var theCharacterTimeout;
  10. var theNewsTimeout;
  11. var theBrowserVersion;
  12. var theWidgetOne;
  13. var theWidgetTwo;
  14. var theSpaceFiller;
  15. var theLeadString;
  16. var theNewsState;
  17. function startTicker(){
  18. // ------ 设置初始数值
  19. theCharacterTimeout = 50;//字符间隔时间
  20. theNewsTimeout = 2000;//新闻间隔时间
  21. theWidgetOne = "_";//新闻前面下标符1
  22. theWidgetTwo = "-";//新闻前面下标符
  23. theNewsState = 1;
  24. theNewsNum = document.getElementById("incoming").children.AllNews.children.length;//新闻总条数
  25. theAddNum = document.getElementById("incoming").children.AddNews.children.length;//补充条数
  26. totalNum =theNewsNum+theAddNum;
  27. theCurrentNews = 0;
  28. theCurrentLength = 0;
  29. theLeadString = " ";
  30. theSpaceFiller = " ";
  31. runTheTicker();
  32. }
  33. // --- 基础函数
  34. function runTheTicker(){
  35. if(theNewsState == 1){
  36. if(CurrentPosion<theNewsNum){
  37. setupNextNews();
  38. }
  39. else{
  40. setupAddNews();
  41. }
  42. CurrentPosion++;
  43. if(CurrentPosion>=totalNum||CurrentPosion>=1){
  44. CurrentPosion=0;//最多条数不超过num_gun条
  45. }
  46. }
  47. if(theCurrentLength != theNewsText.length){
  48. drawNews();
  49. }
  50. else{
  51. closeOutNews();
  52. }
  53. }
  54. // --- 跳转下一条新闻
  55. function setupNextNews(){
  56. theNewsState = 0;
  57. theCurrentNews = theCurrentNews % theNewsNum;
  58. theNewsText = document.getElementById("AllNews").children[theCurrentNews].children.Summary.innerText;
  59. theTargetLink = document.getElementById("AllNews").children[theCurrentNews].children.Summary.children[0].href;
  60. theCurrentLength = 0;
  61. document.all.hottext.href = theTargetLink;
  62. theCurrentNews++;
  63. }
  64. function setupAddNews() {
  65. theNewsState = 0;
  66. theCurrentNews = theCurrentNews % theAddNum;
  67. theNewsText = document.getElementById("AllNews").children[theCurrentNews].children.Summary.innerText;
  68. theTargetLink = document.getElementById("AllNews").children[theCurrentNews].children.Summary.children[0].href;
  69. theCurrentLength = 0;
  70. document.all.hottext.href = theTargetLink;
  71. theCurrentNews++;
  72. }
  73. // --- 滚动新闻
  74. function drawNews(){
  75. var myWidget;
  76. if((theCurrentLength % 2) == 1){
  77. myWidget = theWidgetOne;
  78. }
  79. else{
  80. myWidget = theWidgetTwo;
  81. }
  82. document.all.hottext.innerHTML = theLeadString + theNewsText.substring(0,theCurrentLength) + myWidget + theSpaceFiller;
  83. theCurrentLength++;
  84. setTimeout("runTheTicker()", theCharacterTimeout);
  85. }
  86. // --- 结束新闻循环
  87. function closeOutNews(){
  88. document.all.hottext.innerHTML = theLeadString + theNewsText + theSpaceFiller;
  89. theNewsState = 1;
  90. setTimeout("runTheTicker()", theNewsTimeout);
  91. }
  92. window.onload=startTicker;
蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

DOM常见的操作方式有哪些

seo达人

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

1.什么是DOM

DOM 是 Document Object Model(文档对象模型)的缩写。


DOM是中立于平台和语言的接口,它允许程序和脚本动态地访问和更新文档的内容、结构和样式。


在 HTML DOM中,所有事物都是节点。DOM 是被视为节点树的 HTML。


什么是节点
2.什么是DOM节点
HTML 文档中的所有内容都是节点


整个文档是一个文档节点


每个 HTML 元素是元素节点


HTML 元素内的文本是文本节点


每个 HTML 属性是属性节点


注释是注释节点


demo
3.常见的DOM属性
属性是节点(HTML 元素)的值,您能够获取或设置。


innerHTML 属性
nodeName 属性


nodeName 属性规定节点的名称


元素节点的 nodeName 与标签名相同


属性节点的 nodeName 与属性名相同


文本节点的 nodeName 始终是 #text


文档节点的 nodeName 始终是 #document


nodeValue 属性
nodeValue 属性规定节点的值。


元素节点的 nodeValue 是 undefined 或 null


文本节点的 nodeValue 是文本本身


属性节点的 nodeValue 是属性值


4.访问元素的方法



通过使用 getElementById() 方法


通过使用 getElementsByTagName() 方法


通过使用 getElementsByClassName() 方法


5.修改元素的方法
改变 HTML 内容


document.getElementById("p1").innerHTML="New text!";


改变 CSS 样式


document.getElementById("p2").style.color="blue";


改html和css
追加子元素的方法


首先必须创建该元素(元素节点),然后把它追加到已有的元素上。var para=document.createElement("p");


创建新的 HTML 元素 - appendChild() 在父元素的最后追加


创建新的 HTML 元素-element.insertBefore(para,child);在指定位置给父级追加子元素


删除 HTML 元素,您必须清楚该元素的父元素:parent.removeChild(child);


替换 HTML 元素:parent.replaceChild(para,child); 方法


6.DOM - 事件
允许 JavaScript 对 HTML 事件作出反应


onclick 事件——当用户点击时


onload 事件——用户进入


onunload 事件——用户离开


onmouseover事件——鼠标移入


onmouseout事件——鼠标移出


onmousedown事件——鼠标按下


onmouseup 事件——鼠标抬起


7.参考文献



8.更多讨论

问题1:getElementsByClassName() 使用时需要注意的地方

回答:它取出来的是个数组,及时只有一个那也是数组对象,所以改变指定元素时需使用角标

问题2:innerHTML 和innerText的区别

回答:innerText替换是会将标签替换成字符串,而innerHTML 则会保留标签插入到节点当中

问题3:dom事件

回答:事件是文档或者浏览器窗口中发生的,特定的交互瞬间。事件是用户或浏览器自身执行的某种动作,如click,load和mouseover都是事件的名字。事件是javaScript和DOM之间交互的桥梁。

事件发生,调用它的处理函数执行相应的JavaScript代码给出响应。


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




HTML简单知识的总结

seo达人

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

基本格式:

<!DOCTYPE  HTML>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

<title>制作我的第一个网页</title>

<style type="text/css">

h1{font-size;color;text-align:center}

</style>

</head>

<body>

<h1>Hello World! </h1>

</body>

</html>

注释:<!--注释文本-->

强调语气:<strong>,<em>:前者实现加粗再加粗,后者实现加粗加斜   体。

<span>写在style 里设置单独样式。

<q></q>标签:引用简短文本,使引用的诗句等自己出现双引号

<blockquote>: 引用长文本,增加缩进量。

<br />: 换行标签。

  代码之间实现空格。

<hr />: 段落之间分隔的横线。

<address>: 定义一个地址(比如电子邮件地址)  ,签名或者文档的作者身份。在浏览器上显示的样式为斜体。

<code>: 加入简短代码。

<pre>: 加入一段长代码。


Ul-li标签: 添加新闻信息列表, 图片列表, 无序文字列表

Ol-li 标签:添加有序列表,与ul-li 标签类似。

<div> :把一些独立的逻辑部分划分出来,形成栏目板块。其中还可使用

<div  id=  >给板块命名。

<table>: 制作表格。 

CSS 样式为表格添加边框:<style  type=”text/css”>

黑色边框: table tr td,th{border:1px solid #000;}</style>

<caption>为表格添加标题和摘要。  <table  summary=’’”表格简介文本”>

<caption>标题文本</caption> </table>

<a>  实现超链接。<a href=”目标网址”    title=“鼠标滑过显示的文本”>链接显示的文本</a>    默认在当前浏览器窗口打开,添加targetblank  在新的浏览器窗口打开。

<mailto>  在网页中链接Email 地址。  <a href=”mailto:  yy@qqcom ?

Cc抄送地址=zsq@qqcom  &  bcc密件抄送地址=zjj@qqcom  &

subject=”主题”  &  body=“邮件内容”>发送</a> 给多个收件人发送,用分号隔开。第一个参数用?开头,之后用 &隔开。 

<img> 添加图片。Src=”标识图像的位置。” alt=”指定图像的描述性文本,当图像不可见时(下载不成功时),可看到该属性指定的文本”

Title=“提供在图像可见时对图像的描述(鼠标滑过图片时显示的文本)”

<form>  表单标签,与用户交互使得浏览器可以处理用户的数据。

<form  method=”数据传送的方式get/postaction=”浏览器输入的数据被传送到的地方,如一个 PHP 页面savephp””

<label  for="username">用户名:</label>

<input type="text" name="username" id="username" value="" />

<label  for="pass">密码:</label>

<input type="password" name="pass" id="pass" value="" />    用户名: 肯定存,啊 密码:

表单文本输入框,密码输入框:<form><input  type=text/password

name=”名称(以备后台使用)” value=“文本(设置默认值,提示作用)”>

输入<textarearows(height)=”行数” cols(width)

=”列数”>文本</textarea>

<input type=”radio/checkbox)”

value=”  值 ” name=”  名 称 ” checked=  “  checked  ”  /> 当 设 置

checked=”checked”时,该选项被默认选中。同一组按钮,name 取值必须相同。

下拉列表框<select>:<label> XX </label>

<select>

<option value=”读书” selected=selected被默>读书</option></select>

提交按钮  submit<input  type=”submit”  value=”提交”>重置按钮  reset<input  type=”reset”  value=”重置”>

<label><label for=”控件id 名称”>慢跑  </label>

<input  type=”checkbox”  name=”gender”  id=”jogging”  />

for 属性的值与id 属性值一定要相同。

Placeholder<input  type=”email”  id=”email”  placeholder=”Enter  email”>该提示会在输入字段为空时显示,并会在字段获得焦点时消失。

CSS 样式:定义文本的显示样式,如字体大小(font-size),颜色(color),加粗(font-weight:bold)等。

注释语句:/*注释语句*/。

内联式 CSS 样式:<p  style=”color:red    font-size:12px”>红色字</p>

嵌入式 CSS 样式:<style  type=”text/css”>span{  }</style>

 CSS 在head 里写:<link href=”XX。css” rel=”stylesheet”

type=”text/css”>,在XX。css 里写:span{  }

三种方式的优先级:相同权值下,内联式  >嵌入式  >外部式。但是,嵌入式 >外部式的前提为嵌入式的位置一定在外部式的后面。

选择器:每一条CSS 样式定义由两部分组成:选择器{样式;} 

标签选择器:如<html>,<body>,<h1>,<img>,<p  font,,>。

择器。类选择名称(可任意起名,。XX){css 样式代码;} -> <span class=”XX”></span>

ID #类选择名称(可任意,#XX){css 样式代码;} -><span

id=”XX”></span>只能在文档中使用一次。

>子选择器:用于选择指定标签元素的第一代子元素。【直接后代 first>span{border:1px  solid  red;}  <span>我还是一个<span>胆小如</span>的小女孩</span>

包含后代选择器:加入空格,用于选择指定标签元素下的后辈元素。【所有子后代元素】

通用选择器:由一个*指定,匹配html 中所有标签元素。在style 里:

*{color:red;}

伪类选择符    hover它允许给html 不存在的标签(标签的某种状态)设置样式 a:hover{color:red}鼠标滑过时字体变为红色。

分组选择符    为多个标签元素设置同一个样式。  如h1,p{  }。

继承:有些样式具有继承性如color,有些不具有如border。具有继承性的允许样式不仅应用于某个特定 html 标签元素,而且应用于其后代

权值:标签的权值为1,类选择符的权值为10,ID 选择符的权值最高 100。

p{color:red;} /*权值为1*/

p span{color:green;} /*权值为1+1=2*/

warning{color:white;} /*权值为10*/

p spanwarning{color:purple;} /*权值为1+1+10=12*/

#footer note p{color:yellow;} /*权值为100+10+1=111*/ 特殊性:继承也有权值,但是只有0。1 。

层叠:当有相同权重值时,后面的样式会覆盖前面的样式。

重要性 important :p{color:red!important;}这时p 段落中的文本会显示红色。important 要写在分号前面。



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




vue-router的使用方法介绍input框的23种类型

seo达人

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

input框的类型到底有多少种呢?零零总总算起来有23种。


▍总述

常用的并且能为大多数浏览器所识别的类型大概有:text、password、number、button、reset、submit、hidden、radio、checkbox、file、image、color、range、date、month、week、time、datetime-local。

另外还有一些类型:tel、email、url、datetime、search。这些类型部分浏览器不支持识别或校验。


▍text:文本

代码:

[html] view plain copy
  1. <input type="text" />  

效果:

注意:当input没有填写类型时,默认为文本类型。

[html] view plain copy
  1. <input />  


▍password:密码

代码:

[html] view plain copy
  1. <input type="password" />  

效果:


▍number:数字

代码:

[html] view plain copy
  1. <input type="number" />  

效果:


▍button:按钮

代码:

[html] view plain copy
  1. <input type="button" value="我是按钮" />  

效果:


▍tel:电话

代码:

[html] view plain copy
  1. <input type="tel" />  

效果:

注意:tel类型似乎没有什么实际作用。


▍email:邮件

代码:

[html] view plain copy
  1. <input type="email" />  

效果:

注意:火狐对email类型有校验,360浏览器无校验。


▍file:文件

代码:

[html] view plain copy
  1. <input type="file" />  

效果:


▍range:滑动条

代码:

[html] view plain copy
  1. <input type="range" />  

效果:


▍date:日期

代码:

[html] view plain copy
  1. <input type="date" />  

效果:


▍month:月份

代码:

[html] view plain copy
  1. <input type="month" />  

效果:


▍week:周

代码:

[html] view plain copy
  1. <input type="week" />  

效果:


▍time:时间

代码:

[html] view plain copy
  1. <input type="time" />  

效果:


▍datetime:时间、日、月、年(UTC时间)

代码:

[html] view plain copy
  1. <input type="datetime" />  

效果:

注意:火狐、360浏览器都对datetime不支持,会按照text类型处理。


datetime-local:时间、日、月、年(本地时间)

代码:

[html] view plain copy
  1. <input type="datetime-local" />  

效果:


▍radio:单选框

代码:

[html] view plain copy
  1. <input type="radio" name="man" id="man" value="man"/><label for="man"></label>  
  2. <input type="radio" name="man" id="women" value="woman"/><label for="woman"></label>  

效果:


▍checkbox:复选框

代码:

[html] view plain copy
  1. <input type="checkbox" name="interest" value="run" id="run" /><label for="run">跑步</label>  
  2. <input type="checkbox" name="interest" value="guitar" id="guitar" /><label for="guitar">吉他</label>  
  3. <input type="checkbox" name="interest" value="yoga" id="yoga" /><label for="yoga">瑜伽</label>  
  4. <input type="checkbox" name="interest" value="read" id="read" /><label for="read">阅读</label>  

效果:


▍image:图片

代码:

[html] view plain copy
  1. <input type="image" src="http://p0.so.qhimgs1.com/bdr/_240_/t01cbdeda95800117ac.jpg" />  

效果:


▍color:颜色

代码:

[html] view plain copy
  1. <input type="color" />  

效果:


▍search:搜索框

代码:

[html] view plain copy
  1. <input type="search" />  

效果:

注意:search似乎与text的效果没有什么区别。。。


▍reset:重置按钮

代码:

[html] view plain copy
  1. <input type="reset" />  

效果:

注意:reset按钮一般用于form表单中


▍submit:提交按钮

代码:

[html] view plain copy
  1. <input type="submit" />  

效果:

注意:submit按钮一般用于form表单中


▍hidden:隐藏

代码:

[html] view plain copy
  1. <input type="hidden" />  

效果:


注意:hidden类型会将input隐藏,所以什么都看不到,而且被隐藏的input框也不会占用空间。


▍url:路径

代码:

[html] view plain copy
  1. <input type="tel" />  

效果:

注意:火狐对url类型有校验,360浏览器无校验。


▍写在结尾

总的来说,目前input框也就只有这23种类型,虽然有的类型可能用不上一两次甚至是一次都用不上,但是了解一下还是不错的。



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




vue-router的使用方法介绍

seo达人

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

vue-router

对于大多数单页面应用,都推荐使用官方支持的 vue-router 库。

学习网址:https://router.vuejs.org/installation.html#direct-download-cdn

提示:本篇博客仅仅介绍搭建项目之后,再下载vue-router的情况,并非搭建项目是直接引入vue-router。

一、安装方法(npm方式)

在终端运行以下指令

[html] view plain copy
  1. npm install vue-router  

注意:--save 与 --save-dev 的区别

--save(可以省略) 下载的第三方依赖到package.js中的dependencies。

--save-dev 下载开发时依赖,指环境配置,下载到package.js中的devDependencies,webpack、bable等等均属于开发

时依赖。

二、导入与使用

vue-router下载之后,需要在入口文件main.js导入,具体做法如下:

[javascript] view plain copy
  1. Vue.use(VueRouter);  
  2. Vue.use(VueAxios, axios);  
  3.   
  4. // routes:数组,在该数组中配置所有的路由;  
  5. const routes = [  
  6.   {path:'/',component:myHome,name:'home'},  
  7.   {path:'/product/:productName/:price',component:myProduct,name:'product'}  
  8. ];  
  9. // 创建router实例  
  10. const router = new VueRouter({  
  11.   routes  
  12. });  
  13. /* eslint-disable no-new */  
  14. new Vue({  
  15.   el: '#app',  
  16.   // 引入到根实例中才可以使用导航功能  
  17.   router,  
  18.   components: {App},  
  19.   template: '<App/>',  
  20.   data(){  
  21.     return {  
  22.   
  23.     }  
  24.   }  
  25. })  

三、官网介绍使用步骤

网址:https://router.vuejs.org/zh/guide/#javascript

[javascript] view plain copy
  1. // 0. 如果使用模块化机制编程,导入Vue和VueRouter,要调用 Vue.use(VueRouter)  
  2.   
  3. // 1. 定义 (路由) 组件。  
  4. // 可以从其他文件 import 进来  
  5. const Foo = { template: '<div>foo</div>' }  
  6. const Bar = { template: '<div>bar</div>' }  
  7.   
  8. // 2. 定义路由  
  9. // 每个路由应该映射一个组件。 其中"component" 可以是  
  10. // 通过 Vue.extend() 创建的组件构造器,  
  11. // 或者,只是一个组件配置对象。  
  12. // 我们晚点再讨论嵌套路由。  
  13. const routes = [  
  14.   { path: '/foo', component: Foo },  
  15.   { path: '/bar', component: Bar }  
  16. ]  
  17.   
  18. // 3. 创建 router 实例,然后传 `routes` 配置  
  19. // 你还可以传别的配置参数, 不过先这么简单着吧。  
  20. const router = new VueRouter({  
  21.   routes // (缩写) 相当于 routes: routes  
  22. })  
  23.   
  24. // 4. 创建和挂载根实例。  
  25. // 记得要通过 router 配置参数注入路由,  
  26. // 从而让整个应用都有路由功能  
  27. const app = new Vue({  
  28.   router  
  29. }).$mount('#app')  
  30.   
  31. // 现在,应用已经启动了!  

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




日历

链接

个人资料

蓝蓝设计的小编 http://www.lanlanwork.com

存档