Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

14 实现on事件指令 #16

Open
xwjie opened this issue Jan 17, 2018 · 0 comments
Open

14 实现on事件指令 #16

xwjie opened this issue Jan 17, 2018 · 0 comments

Comments

@xwjie
Copy link
Owner

xwjie commented Jan 17, 2018

就是 v-on, 缩写为 @

代理组件的methods方法

function initMethods(vm: any, methods: Object) {
  for (const key in methods) {
    vm[key] = methods[key] == null ? noop : bind(methods[key], vm)
  }
}

/**
 * Simple bind, faster than native
 */
export function bind (fn: Function, ctx: Object): Function {
  function boundFn (a) {
    const l: number = arguments.length
    return l
      ? l > 1
        ? fn.apply(ctx, arguments)
        : fn.call(ctx, a)
      : fn.call(ctx)
  }
  // record original fn length
  boundFn._length = fn.length
  return boundFn
}

修改生成render字符串方法

/**
 * 解析属性
 * @param {*} node
 */
function genAttrStr(node: any) {
  let attrs = node.attrsMap

  if (!attrs) {
    return ""
  }

  let propsStr: string = ''
  let styleStr: string = ''
  let onStr: string = ''

  // why not use for..in, see eslint `no-restricted-syntax`
  Object.keys(attrs).forEach(attrname => {
    let str = ''
    let isEvent = false
    const val = attrs[attrname].trim()

    // 如果是数据绑定,则后面的是表达式
    if (attrname.charAt(0) == ':') {
      str = JSON.stringify(attrname.substr(1)) + ':' + val + ','
      attrname = attrname.substr(1).toLocaleLowerCase()
    }
    else if (attrname.charAt(0) == '@') {
      str = JSON.stringify(attrname.substr(1)) + ':' + getFunctionStr(val) + ','
      isEvent = true
      attrname = attrname.substr(1).toLocaleLowerCase()
    }
    else {
      str = JSON.stringify(attrname) + ':' + JSON.stringify(val) + ','
    }

    // class已经处理了。
    if (attrname !== 'class') {
      if (isEvent) {
        onStr += str
      } else if (isStyle(attrname)) {
        styleStr += str
      }
      else {
        propsStr += str
      }
    }
  })

  let str = '';

  if (propsStr != '') {
    str += `props:{${propsStr}},`
  }

  if (styleStr != '') {
    str += `style:{${styleStr}},`
  }

  if (onStr != '') {
    str += `on:{${onStr}},`
  }

  return str;
}


function isStyle(name: string) {
  return name === 'style'
}

function isFuncNameStr(name: string): boolean {
  return /[-A-Za-z0-9_]+$/.test(name)
}

function getFunctionStr(funcStr: string): string {
  // 如果只是函数名,加一个()调用
  if (isFuncNameStr(funcStr)) {
    funcStr += '(event)'
  }

  return `function($event){${funcStr}} `
}

测试代码

//D:\OutPut\VUE\VueStudyNote\Xiao\example\14 directive-on.html

<!DOCTYPE html>
<html>
<head>
	<title>Xiao框架之helloworld</title>
	<script src="../dist/xiao.js"></script>
</head>
<body>
<h1>@(on)指令测试</h1>
<div id="demo1">
	<button @click="click1">{{btnText}}</button><br/>
	<button @click="click2(count>1)">按钮2</button><br/>
	<button @click="btnText='改变值'">按钮3</button>
</div>
<script>
var app = new Xiao({
	data:{
		btnText: "按钮1",
		count:2
	},
	methods:{
		click1 : function(e){
			console.log('按钮1', e);
		},
		click2 : function(flag){
			console.log('按钮2:' + this.count, flag);
		},
	}
});

app.$mount("#demo1");

setTimeout(function(){
	app.count = 1;
}, 3000);

</script>

</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant