点点阅读app正版
24.91MB · 2025-10-31
多年前在网上看到一场开发者的讨论,
# 代码约架?Vue.js和Binding.scala两大框架作者的PK
尽管没有用过scala, 但总是对这一对比念念不忘. 如果确实有优秀的工具能够简化代码量, 那自然是好事, 今天就借助AI的力量, 对前端常用的vue和react代码进行一个简单的比较.
以下代码都用 秘塔AI搜索 生成, 简单进行了清理.
提示词:
react 调用github的公开API, 获取头像数据
import { useState, useEffect } from "react";
function App() {
  const [input, setInput] = useState("octocat");
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState("");
  const fetchUser = (username) => {
    setLoading(true);
    fetch(`https://api.github.com/users/${username}`)
      .then((res) => {
        if (!res.ok) throw new Error(`HTTP ${res.status}`);
        return res.json();
      })
      .then(setUser)
      .catch((e) => setError(e.message))
      .finally(() => setLoading(false));
  };
  useEffect(() => {
    fetchUser(input);
  }, [input]);
  return (
    <div>
      <input
        value={input}
        onChange={(e) => setInput(e.target.value.trim())}
        placeholder="输入 GitHub 用户名"
      />
      {loading && <p>加载中…</p>}
      {error && <p>错误:{error}</p>}
      {user && (
        <div style={{ marginTop: "1rem", textAlign: "center" }}>
          <img
            src={user.avatar_url}
            alt={user.login}
          />
          <h3>{user.name || user.login}</h3>
        </div>
      )}
    </div>
  );
}
看一下vue
<template>
  <div class="github-avatar">
    <input v-model="username" placeholder="GitHub 用户名" @keyup.enter="fetchUser" />
    <button @click="fetchUser">获取头像</button>
    <!-- 当 data.avatar_url 有值时显示头像 -->
    <div v-if="user">
      <h3>{{ user.name || user.login }}</h3>
      <img :src="user.avatar_url" alt="GitHub Avatar" class="avatar" />
      <p>简介:{{ user.bio }}</p>
    </div>
    <!-- 错误提示 -->
    <p v-if="error" class="error">{{ error }}</p>
  </div>
</template>
<script setup>
import { ref } from 'vue'
import axios from 'axios'
const username = ref('')          // 输入框绑定的用户名
const user = ref(null)            // 保存返回的用户对象
const error = ref('')             // 错误信息
// 调用 GitHub 公共 API
async function fetchUser() {
  if (!username.value) {
    error.value = '请先输入用户名'
    return
  }
  error.value = ''
  try {
    const resp = await axios.get(`https://api.github.com/users/${username.value}`)
    // resp.data 中包含 avatar_url 等字段[[1]]
    user.value = resp.data
  } catch (e) {
    if (e.response && e.response.status === 404) {
      error.value = '用户不存在'
    } else {
      error.value = '请求出错,请稍后再试'
    }
    user.value = null
  }
}
</script>
可以看到对于简单的需求, 二者的代码量和行数基本一样. 比较大的区别在于vue的写法更接近传统的html结构, 思路上也是首先有静态模板, 之后是动态逻辑, 中间是数据绑定关系. 而react的模板写在最后, 和js逻辑混在一起, 好处是减少了编译负担, 代价是思路和习惯要转个弯才能适应. 当然vue这种写法也未必就是最好的, 只是对于前端来说, vue提供了一种更平缓的转换曲线, 因此也吸引了众多开发者.
为便于对比把binding.scala的代码也放一下, 由于比较小众, 没有用AI生成的, 而是直接复制了框架作者的代码.
@dom def render = {
  val githubUserName = Var("")
  def inputHandler = { event: Event => githubUserName := event.currentTarget.asInstanceOf[Input].value }
  <div>
    <input type="text" oninput={ inputHandler }/>
    <hr/>
    {
      val name = githubUserName.bind
      if (name == "") {
        <div>Please input your Github user name</div>
      } else {
        val githubResult = FutureBinding(Ajax.get(s"https://api.github.com/users/${name}"))
        githubResult.bind match {
          case None =>
            <div>Loading the avatar for { name }</div>
          case Some(Success(response)) =>
            val json = JSON.parse(response.responseText)
            <img src={ json.avatar_url.toString }/>
          case Some(Failure(exception)) =>
            <div>{ exception.toString }</div>
        }
      }
    }
  </div>
}
这只是核心代码, 前后还有一些导入和声明. 可以看到该技术借助宏和元编程能力, 把界面和逻辑代码尽可能紧密的结合在一起, 虽然确实减少一些代码行数, 但是否足够清晰易懂, 恐怕还是要划个问号.
今天, 前端, 或者更广泛些, 客户端的代码究竟如何书写, 还没有标准答案. 这个问题的本质是想要兼顾静态展示和动态交互, 但可能并没有一种通用的万能方法, 只能由开发者根据二者的比例作出取舍.
 
                    