专栏首页前端有的玩学会使用Vue JSX,一车老干妈都是你的

学会使用Vue JSX,一车老干妈都是你的

❝君自前端来,应知前端事。需求时时变,bug改不完。 ❞

连续几篇文章,每篇都有女神,被掘友给吐槽了,今天不提了女神了,反正女神都是别人的(扎心了)。这两天小编看了腾讯与老干妈的事情,晚上馒头夹老干妈吃起来都感觉很带劲。今天这篇文章将给大家小编在项目中使用JSX的一些实战经验。其实一般情况下写Vue还是比较推荐template的写法的,但是有时候我们真的需要更灵活的去做一些功能,这时候就需要用到JSX了。

介绍一下JSX

JSX 简介

JSX是一种Javascript的语法扩展,JSX = Javascript + XML,即在Javascript里面写XML,因为JSX的这个特性,所以他即具备了Javascript的灵活性,同时又兼具html的语义化和直观性。

应用场景

为了让大家更方便的去理解JSX的作用及用法,小编先为大家罗列了几个可能会用到JSX的应用场景。

在消息框内添加html

在开发过程中,经常会用到消息框,使用消息框可能的一种写法是这样的

Message.alert({
  messge: '确定要删除?',
  type: 'warning'
})

但是有时候产品或UI希望message可以自定义一些样式,这时候你可能就需要让Message.alert支持JSX了(当然也可以使用插槽/html等方式解决)

Message.alert({
  // 此处使用了JSX
  messge: <div>确定要删除<span style="color:red">学习子君Vue系列文章</span>的笔记?</div>,
  type: 'warning'
})

函数式组件

在小编前面的文章实战技巧,Vue原来还可以这样写中介绍了为什么要使用函数式组件,及函数式组件与普通组件的区别。虽然在Vue.2.5之后,函数式组件也可以使用模板语法,但使用JSX可能会更方便一些(个人理解)

export default {
  // 通过配置functional属性指定组件为函数式组件
  functional: true,
  /**
   * 渲染函数
   * @param {*} h
   * @param {*} context 函数式组件没有this, props, slots等都在context上面挂着
   */
  render(h, context) {
    const { props } = context
    if (props.avatar) {
      return <img src={props.avatar}></img>
    }
    return <img src="default-avatar.png"></img>
  }
}

一个表单的需求

为了方便快速开发管理系统,小编对所使用的UI库中的表单进行了二次封装,封装之后的效果如下(仅供参考):

<template>
  <custom-form v-model="formData" :fields="fields" />
</template>
<script>
export default {
  data() {
    return {
      formData: {},
      fields: Object.freeze([
        {
          label: '字段1',
          props: 'field1',
          type: 'input'
        },
        {
          label: '字段2',
          props: 'field2',
          type: 'number'
        }
      ])
    }
  }
}
</script>

这样封装之后,定义表单时,只需要定义简单的JSON即可快速完成表单开发,但有时候会有一些特殊的需求,比如希望可以给输入框后面加一个按钮或者图标之类的,这时候就需要考虑使用JSX去处理了

{
  label: '字段2',
  props: 'field2',
  type: 'number',
  // 会渲染到表单元素后面
  renderSuffix() {
    return <button onClick={this.$_handleSelect}>选择</button>
  }
}

其他一些场景

比如我们一条数据需要根据状态不同,定义不同的展现方式,这时候你可能会想到用策略模式,这时候如果将每一个策略都写成一个JSX,那么就不需要针对每一个策略定义一个单文件组件了。当然如果你说,我就喜欢用JSX,那么所有的场景你都可以用。

❝为了您阅读后面的内容时获得更好的阅读体验,建议您先点击一下电脑左侧或手机下方的大拇指图标,让页面色彩变得更丰富。 ❞

学习JSX,先了解一下createElement

提到JSX,不可避免的就要提到createElement,当你看完本节,你会发现,奇怪的知识又增多了。

Vue编译后的代码看createElement

你是否看过写的Vue代码经过编译之后的样子,比如下面这段代码

<template>
  <div>我是子君,我的公众号是<span class="emphasize">前端有的玩</span></div>
</template>

小编对这段代码进行编译之后,得到下面这段代码

function () {
  var e = this,
  // e._self._c 对应源码里面的createElement
  t = e._self._c;
  // 返回了一个 createElement('div',[])
  return t("div", [
    // e._v 对应源码里面的createTextVNode
    e._v("我是子君,我的公众号是"),
    t("span", { staticClass: "emphasize" }, [e._v("前端有的玩")]),
  ]);
}

通过对上面的代码进行分析,不难发现,Vue模板中的每一个元素编译之后都会对应一个createElement,那么这个createElement到底是什么,嗯,这个你面试的时候也许已经提到过了。

那么什么是createElement

无论是Vue还是React,都存在createElement,而且作用基本一致。可能你对createElement不是很了解,函数名翻译过来就是增加一个元素,但他的返回值你一定知道。createElement函数返回的值称之为虚拟节点,即VNode,而由VNode扎堆组成的树便是大名鼎鼎,面试必问的虚拟DOM

createElement函数的参数,在这里小编偷个懒抄一下Vue官方文档

// @returns {VNode}
createElement(
  // {String | Object | Function}
  // 一个 HTML 标签名、组件选项对象,或者
  // resolve 了上述任何一种的一个 async 函数。必填项。
  'div',

  // {Object}
  // 一个与模板中 attribute 对应的数据对象。可选。
  {
    // (详情见下一节)
  },

  // {String | Array}
  // 子级虚拟节点 (VNodes),由 `createElement()` 构建而成,
  // 也可以使用字符串来生成“文本虚拟节点”。可选。
  [
    '先写一些文字',
    createElement('h1', '一则头条'),
    createElement(MyComponent, {
      props: {
        someProp: 'foobar'
      }
    })
  ]
)

从上面可以看出createElement一共有三个参数,三个参数分别是

  • 第一个参数是需要渲染的组件,可以是组件的标签,比如div;或者是一个组件对象,也就是你天天写的export default {};亦或者可以是一个异步函数。
  • 第二个参数是这个组件的属性,是一个对象,如果组件没有参数,可以传null(关于组件的属性,下文将依次介绍)
  • 第三个参数是这个组件的子组件,可以是一个字符串(textContent)或者一个由VNodes组成的数组

createElement写一个组件吧

表单示例

假设我们需要开发一个下面这样的表格(element-ui的)

用模板代码去开发

如果我们用模板代码去开发这个表单,那么代码大概就长这样

<el-form :inline="true" :model="formInline" class="demo-form-inline">
  <el-form-item label="审批人">
    <el-input v-model="formInline.user" placeholder="审批人"></el-input>
  </el-form-item>
  <el-form-item label="活动区域">
    <el-select v-model="formInline.region" placeholder="活动区域">
      <el-option label="区域一" value="shanghai"></el-option>
      <el-option label="区域二" value="beijing"></el-option>
    </el-select>
  </el-form-item>
  <el-form-item>
    <el-button type="primary" @click="onSubmit">查询</el-button>
  </el-form-item>
</el-form>

createElement去实现

如果我们直接将上面的代码转换为用createElement去实现,那么代码将会是这样的

export default {
 methods: {
    $_handleChangeUser(value) {
      this.formInline.user = value
    }
  },
  render(createElement) {
    return createElement(
      'ElForm',
      {
        props: {
          inline: true,
          model: this.formInline
        },
        staticClass: 'demo-form-inline'
      },
      [
        createElement(
          'ElFormItem',
          {
            props: {
              label: '审批人'
            }
          },
          [
            createElement('ElInput', {
              props: {
                value: this.formInline.user
              },
              attrs: {
                placeholder: '审批人'
              },
              on: {
                input: this.$_handleChangeUser
              }
            })
          ]
        ),
        createElement(
          'ElFormItem',
          {
            props: {
              label: '活动区域'
            }
          },
          [
            createElement(
              'ElSelect',
              {
                props: {
                  value: this.formInline.region,
                  placeholder: '活动区域'
                }
              },
              [
                createElement('ElOption', {
                  props: {
                    label: '区域一',
                    value: 'shanghai'
                  }
                }),
                createElement('ElOption', {
                  props: {
                    label: '区域二',
                    value: 'beijing'
                  }
                })
              ]
            )
          ]
        ),
        createElement('ElFormItem', null, [
          createElement(
            'ElButton',
            {
              props: {
                type: 'primary'
              },
              on: {
                click: this.$_handleSubmit
              }
            },
            '查询'
          )
        ])
      ]
    )
  }
}

看到上面的代码,你可能会惊呼,代码好多啊,好痛苦,想当年发明JSX的人刚开始天天也是写createElement,写的直掉头发,太痛苦了,然后就使劲挠头,当额头锃光发亮的时候,终于想到了一种新的语法,就是JSX。从此之后,头发呼呼的又长回来了(本段纯属虚构)。

看到上面代码,你会发现有一个render函数,这个函数叫做渲染函数,相当于通过createElementJSX去实现功能的主入口方法。而且你熟悉的v-model也没见了,而是用value + input代替了。

是时候使用JSX代替createElement

看到上面用createElement去实现组件,太麻烦了,别说工作效率提高了,就是那些嵌套可以嵌套正确就很赞了,所以我们需要用JSX去简化整个逻辑。

methods: {
  $_handleInputUser(value) {
    this.formInline.user = value
  },
  $_handleChangeRegion(value) {
    this.formInline.region = value
  },
  $_handleSubmit() {}
},
  /**
  *将 h 作为 createElement 的别名是 Vue 生态系统中的一个通用惯例,实际上也是 JSX 所要求的。从 Vue 的 Babel 插件的 3.4.0   *版本开始,我们会在以 ES2015 语法声明的含有 JSX 的任何方法和 getter 中 (不是函数或箭头函数中) 自动注入 
  *const h = this.$createElement,这样你就可以去掉 (h) 参数了。对于更早版本的插件,如果 h 在当前作用域中不可用,应用会抛错。
 */
render(h) {
    return (
      <ElForm inline model={this.formInline} class="demo-form-inline">
        <ElFormItem label="审批人">
          <ElInput
            value={this.formInline.user}
            onInput={this.$_handleInputUser}
            placeholder="审批人"
          ></ElInput>
        </ElFormItem>
        <ElFormItem label="活动区域">
          <ElSelect
            value={this.formInline.region}
            onChange={this.$_handleChangeRegion}
            placeholder="活动区域"
          >
            <ElOption label="区域一" value="shanghai"></ElOption>
            <ElOption label="区域二" value="beijing"></ElOption>
          </ElSelect>
        </ElFormItem>
        <ElFormItem>
          <ElButton type="primarty" onClick={this.$_handleSubmit}>
            查询
          </ElButton>
        </ElFormItem>
      </ElForm>
    )
  }

看了上面的代码,大家其实会发现用JSXtemplate的语法都属于xml的写法,而且也比较像,但实质上还是有许多区别的,下面小编将为大家一一分析

没有v-model怎么办,还有其他指令可以用吗?

当你选择使用JSX的时候,你就要做好和指令说拜拜的时候了,在JSX中, 你唯一可以使用的指令是v-show,除此之外,其他指令都是不可以使用的,有没有感到很慌,这就对了。不过呢,换一个角度思考,指令只是Vue在模板代码里面提供的语法糖,现在你已经可以写Js了,那些语法糖用Js都可以代替了。

v-model

v-modelVue提供的一个语法糖,它本质上是由 value属性(默认) + input事件(默认)组成的,如果对自定义v-model不了解的同学建议阅读小编的文章进行了解 绝对干货~!学会这些Vue小技巧,可以早点下班和女神约会了。所以,在JSX中,我们便可以回归本质,通过传递value属性并监听input事件来实现数据的双向绑定

export default {
  data() {
    return {
      name: ''
    }
  },
  methods: {
    // 监听 onInput 事件进行赋值操作
    $_handleInput(e) {
      this.name = e.target.value
    }
  },
  render() {
    // 传递 value 属性 并监听 onInput事件
    return <input value={this.name} onInput={this.$_handleInput}></input>
  }
}

v-if 与 v-for

在模板代码里面我们通过v-for去遍历元素,通过v-if去判断是否渲染元素,在jsx中,对于v-for,你可以使用for循环,array.map来代替,对于v-if,可以使用if语句,三元表达式等来代替

循环遍历列表

const list = ['java', 'c++', 'javascript', 'c#', 'php']
return (
  <ul>
  {list.map(item => {
   return <li>{item}</li>
  })}
  </ul>
)

使用条件判断

const isGirl = false
return isGirl ? <span>小妹,哥哥教你写Vue</span> : <span>鸟你干啥</span>

v-bind

在模板代码中,我们一般通过 v-bind:prop="value":prop="value"来给组件绑定属性,在JSX里面写法也类似

render() {
  return <input value={this.name}></input>
}

v-html 与 v-text

在说v-htmlv-text之前,我们需要先了解一下Vue中的属性,Vue中的属性一共分为三种,第一种是大家写bug时候最常用的props,即组件自定义的属性;第二种是attrs,是指在父作用域里面传入的,但并未在子组件内定义的属性。第三种比较特殊,是domProps,经小编不完全测试,在Vue中,domProps主要包含三个,分别是innerHTML,textContent/innerTextvalue

v-html: 在模板代码中,我们用v-html指令来更新元素的innerHTML内容,而在JSX里面,如果要操纵组件的innerHTML,就需要用到domProps

export default {
  data() {
    return {
      content: '<div>这是子君写的一篇新的文章</div>'
    }
  },
  render() {
    // v-html 指令在JSX的写法是 domPropsInnerHTML
    return <div domPropsInnerHTML={this.content}></div>
  }
}

v-text: 看了上面的v-html,你是不是立即就想到了v-textJSX的写法domPropsInnerText,是的,你没有想错

export default {
  data() {
    return {
      content: '这是子君写的一篇新的文章的内容'
    }
  },
  render() {
    return <div domPropsInnerText={this.content}></div>
  }
}

但实际上我们不需要使用domPropsInnerText,而是将文本作为元素的子节点去使用即可

<div>{this.content}</div>

实际上,对于domProps,只有innerHTML才需要使用domPropsInnerHTML的写法,其他使用正常写法即可

我还要监听事件呢

监听事件与原生事件

当我们开发一个组件之后,一般会通过this.$emit('change')的方式对外暴露事件,然后通过v-on:change的方式去监听事件,很遗憾,在JSX中你无法使用v-on指令,但你将解锁一个新的姿势

 render() {
    return <CustomSelect onChange={this.$_handleChange}></CustomSelect>
  }

JSX中,通过on + 事件名称的大驼峰写法来监听,比如事件icon-click,在JSX中写为onIconClick

有时候我们希望可以监听一个组件根元素上面的原生事件,这时候会用到.native修饰符,有点绝望啊,修饰符也是不能用了,但好在也有替代方案,如下代码

 render() {
    // 监听下拉框根元素的click事件
    return <CustomSelect nativeOnClick={this.$_handleClick}></CustomSelect>
  }

监听原生事件的规则与普通事件是一样的,只需要将前面的on替换为nativeOn

除了上面的监听事件的方式之外,我们还可以使用对象的方式去监听事件

  render() {
    return (
      <ElInput
        value={this.content}
        on={{
          focus: this.$_handleFocus,
          input: this.$_handleInput
        }}
        nativeOn={{
          click: this.$_handleClick
        }}
      ></ElInput>
    )
  }

事件修饰符

和指令一样,除了个别的之外,大部分的事件修饰符都无法在JSX中使用,这时候你肯定已经习惯了,肯定有替代方案的。

.stop :阻止事件冒泡,在JSX中使用event.stopPropagation()来代替

.prevent:阻止默认行为,在JSX中使用event.preventDefault() 来代替

.self:只当事件是从侦听器绑定的元素本身触发时才触发回调,使用下面的条件判断进行代替

if (event.target !== event.currentTarget){
  return
}

.enterkeyCode: 在特定键触发时才触发回调

if(event.keyCode === 13) {
  // 执行逻辑
}

除了上面这些修饰符之外,尤大大为了照顾我们这群CV仔,还是做了一点优化的,对于.once,.capture,.passive,.capture.once,尤大大提供了前缀语法帮助我们简化代码

 render() {
    return (
      <div
        on={{
          // 相当于 :click.capture
          '!click': this.$_handleClick,
          // 相当于 :input.once
          '~input': this.$_handleInput,
          // 相当于 :mousedown.passive
          '&mousedown': this.$_handleMouseDown,
          // 相当于 :mouseup.capture.once
          '~!mouseup': this.$_handleMouseUp
        }}
      ></div>
    )
  }

对了,还有插槽

插槽就是子组件中提供给父组件使用的一个占位符,插槽分为默认插槽,具名插槽和作用域插槽,下面小编依次为你带来每种在JSX中的用法与如何去定义插槽。

默认插槽

  • 使用默认插槽

使用element-uiDialog时,弹框内容就使用了默认插槽,在JSX中使用默认插槽的用法与普通插槽的用法基本是一致的,如下代码所示:

 render() {
    return (
      <ElDialog title="弹框标题" visible={this.visible}>
        {/*这里就是默认插槽*/}
        <div>这里是弹框内容</div>
      </ElDialog>
    )
  }

自定义默认插槽

在Vue的实例this上面有一个属性slots,这个上面就挂载了一个这个组件内部的所有插槽,使用this.slots.default就可以将默认插槽加入到组件内部

export default {
  props: {
    visible: {
      type: Boolean,
      default: false
    }
  },
  render() {
    return (
      <div class="custom-dialog" vShow={this.visible}>
        {/**通过this.$slots.default定义默认插槽*/}
        {this.$slots.default}
      </div>
    )
  }
}

具名插槽

  • 使用具名插槽 有时候我们一个组件需要多个插槽,这时候就需要为每一个插槽起一个名字,比如element-ui的弹框可以定义底部按钮区的内容,就是用了名字为footer的插槽
 render() {
    return (
      <ElDialog title="弹框标题" visible={this.visible}>
        <div>这里是弹框内容</div>
        {/** 具名插槽 */}
        <template slot="footer">
          <ElButton>确定</ElButton>
          <ElButton>取消</ElButton>
        </template>
      </ElDialog>
    )
  }
  • 自定义具名插槽

在上节自定义默认插槽时提到了slots,对于默认插槽使用this.slots.default,而对于具名插槽,可以使用this.

render() {
    return (
      <div class="custom-dialog" vShow={this.visible}>
        {this.$slots.default}
        {/**自定义具名插槽*/}
        <div class="custom-dialog__foolter">{this.$slots.footer}</div>
      </div>
    )
  }

作用域插槽

使用作用域插槽

有时让插槽内容能够访问子组件中才有的数据是很有用的,这时候就需要用到作用域插槽,在JSX中,因为没有v-slot指令,所以作用域插槽的使用方式就与模板代码里面的方式有所不同了。比如在element-ui中,我们使用el-table的时候可以自定义表格单元格的内容,这时候就需要用到作用域插槽

data() {
    return {
      data: [
        {
          name: '子君'
        }
      ]
    }
  },
  render() {
    return (
      {/**scopedSlots即作用域插槽,default为默认插槽,如果是具名插槽,将default该为对应插槽名称即可*/}
      <ElTable data={this.data}>
        <ElTableColumn
          label="姓名"
          scopedSlots={{
            default: ({ row }) => {
              return <div style="color:red;">{row.name}</div>
            }
          }}
        ></ElTableColumn>
      </ElTable>
    )
  }

自定义作用域插槽

使用作用域插槽不同,定义作用域插槽也与模板代码里面有所不同。加入我们自定义了一个列表项组件,用户希望可以自定义列表项标题,这时候就需要将列表的数据通过作用域插槽传出来。

render() {
    const { data } = this
    // 获取标题作用域插槽
    const titleSlot = this.$scopedSlots.title
    return (
      <div class="item">
        {/** 如果有标题插槽,则使用标题插槽,否则使用默认标题 */}
        {titleSlot ? titleSlot(data) : <span>{data.title}</span>}
      </div>
    )
  }

只能在render函数里面使用JSX

当然不是,你可以定义method,然后在method里面返回JSX,然后在render函数里面调用这个方法,不仅如此,JSX还可以直接赋值给变量,比如下面这段代码

 methods: {
    $_renderFooter() {
      return (
        <div>
          <ElButton>确定</ElButton>
          <ElButton>取消</ElButton>
        </div>
      )
    }
  },
  render() {
    const buttons = this.$_renderFooter()
    return (
      <ElDialog visible={this.visible}>
        <div>这里是一大坨内容</div>
        <template slot="footer">{buttons}</template>
      </ElDialog>
    )
  }

结语

❝不要吹灭你的灵感和你的想象力; 不要成为你的模型的奴隶。——文森特・梵高 ❞

本文分享自微信公众号 - 前端有的玩(gh_918bae0a9616),作者:子君

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-07-06

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【Vue进阶】手把手教你在 Vue 中使用 JSX

    JSX 是一种 Javascript 的语法扩展,JSX = Javascript + XML,即在 Javascript 里面写 XML,因为 JSX 的这个...

    GopalFeng
  • 聊一聊Vue组件模版,你知道它有几种定义方式吗?

    前端组件化开发已经是一个老生常谈的话题了,组件化让我们的开发效率以及维护成本带来了质的提升。

    六小登登
  • React 面试筹备不完全指南

    我们今天主要讲解的内容就是关于 React 面试相关的,我相信你在面试中,也会被问到各种各样的非常多的问题,我举几个例子你看看,在自己心里想一想,你会怎么回答?

    西岭老湿
  • Vue JSX、自定义 v-model

    最初用到 JSX,就是做这个博客的时候。iview 表格组件,不支持像 element 那样直接写 html 代码渲染,只能通过 render 函数渲染,也就是...

    Krry
  • 我在项目中是这样配置Vue的

    在前面的文章中,我为大家带来了许多Vue 实战技巧,也得到了大家的许多好评,但中间还是存在着些许漏洞,在此向大家表示歉意。其实在前面那些技巧之外,我们还可以做的...

    用户1308196
  • 在Vue 3中使用JSX

    各位同学下午好,我是来自字节跳动大力智能前端团队的林成璋,最近半年的业余时间(再加上一些摸鱼的时间)主要在维护 Vue 3 的 Babel JSX Plugin...

    公众号@魔术师卡颂
  • 探索 Vue 3 中的 JSX

    本文为 Vue Conf 2021 分享内容。 分享者:林成璋,目前就职于 字节跳动 大力智能前端 团队

    前端迷
  • 探索 Vue 3 中的 JSX

    各位同学下午好,我是来自字节跳动大力智能前端团队的林成璋,最近半年的业余时间(再加上一些摸鱼的时间)主要在维护 Vue 3 的 Babel JSX Plugin...

    用户4456933
  • Vue 组件开发实践之 scopedSlot 的传递

    在使用Vue开发我们的vhtml-ui的组件库的过程中遇到了组件嵌套组件时需要传递scopedSlot的情况,官方的文档和教程目前还没有比较明确的指引,所以摸着...

    谭伟华
  • 最有效、最全的Vue 2.0 学习路线,各个阶段适用

    对于我这种从0.x版本就开始体验 vuejs 的人来说,当然不算难,那时候没各种脚手架和复杂搭配,仅仅是一个mvvm的解决方案库而已,解决了jq带来的繁琐操作d...

    一墨编程学习
  • Python爬取糗事百科所有段子

    D:\Python\venv\Scripts\python.exe D:/Python/venv/test8.py

    py3study
  • 我为什么不再用 Vue,而改用 React?

    当我走进现代前端开发行业的时候,我做了一个每位开发人员都要做的决策:选择一个合适的框架。当时正逢 jQuery 被淘汰,前端开发者们不再用它编写难看的、非结构化...

    逆锋起笔
  • 学点vue.js的东西,什么都得学点,面试时说不定对方会问什么

    说vue呢也是关注视图层的框架,它嫌react太绕了,redux太麻烦了,然后就说自己很简单,说自己还有双向绑定,好的很,不是小好,是大好。那我今天就写点vue...

    web前端教室
  • 父亲节|有个统计学家老爸是怎样一种体验

    大数据文摘
  • 小程序框架对比 ( WePY / mpvue / Taro )

    众所周知如今市面上端的形态多种多样,手机 Web、ReactNative、微信小程序, 支付宝小程序, 快应用等,每一端都是巨大的流量入口,当业务要求同时在不同...

    Fundebug
  • 拥抱 Vue 3 系列之 JSX 语法

    “别再更新了,学不动了”。这句话不知道出了多少开发者的辛酸。在过去的一年中,Vue 团队一直都在开发 Vue.js 的下一个主要版本,就在 6 月底,尤大更新同...

    政采云前端团队
  • 【免费视频教程】vue+vant实现网易严选移动端app(第一节)

    https://youzan.github.io/vant/#/zh-CN/quickstart

    web前端教室
  • Angular React Vue我应该选择什么?

    为 web 应用选择 JavaScript 开发框架是一件很费脑筋的事。现如今 Angular 和 React 非常流行,并且最近出现的新贵 VueJS 同样博...

    gemron的空间
  • 2016年做前端开发是什么体验?

    有人说,你有什么资格发表这种高谈阔论,实际上是这样的,我在看 lol 比赛直播的时候,有个很有名的主播说过,打到 2400 以上的都去做职业玩家了, 1800-...

    用户4962466

扫码关注云+社区

领取腾讯云代金券