您好!欢迎访问家园网-www.jy.wang!

家园网

头像预览的实现

网络 作者:本站 点击:

头像预览的实现


js代码:

//javascript document
function readFile (){
    var file = document.getElementById("file").files[0];//检查是否为图像文件
    if(!/image\/\w+/.test(file.type))    {
        alert("请确保文件为图像类型");
        return false;
    }    
    var reader = new FileReader();
    reader.readAsDataURL(file); //将文件以Data URL形式进行读入页面
    reader.onload = function(e)    {
       var result=document.getElementById("result");
       result.innerHTML = '<img src="'+this.result+'" alt=""/>'     //在页面上显示文件
    }
}


html代码:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>图片预览</title>
<link href="css/style.css" type="text/css" rel="stylesheet">
</head>

<body>
<div class="mr-cont">
  <h2>个人简历</h2>
  <div>
    <div class="mess">
      <div>
        <p> <span>姓名:</span>
          <input type="text">
        </p>
        <p><span>性别:</span>
          <input type="text">
        </p>
      </div>
      <div>
        <p><span>生日:</span>
          <input type="text">
        </p>
        <p><span>年龄:</span>
          <input type="text">
        </p>
      </div>
      <div>
        <p><span>专业:</span>
          <input type="text">
        </p>
        <p><span>学历:</span>
          <input type="text">
        </p>
      </div>
    </div>
    <div class="photo" id="result"></div>
  </div>
  <div class="expr">
    <h3>校内经历和所获荣誉</h3>
    <div class="border"><textarea cols="84" rows="11"></textarea></div>
  </div>
  <div class="expr">
    <h3>社会经历</h3>
    <div><textarea cols="84" rows="11"></textarea></div>
  </div>
  <div class="btn">
  <input type="button"  value="选择头像">
    <input type="file" id="file">
    <input type="button" value="预览" onClick="readFile ()">
  </div>
 
</div>
</body>
<script type="text/javascript" src="js/js.js"></script>
</html>


上面的代码是如何实现选择文件后点击预览按钮,在右侧头像区域显示图片的功能的?


图片预览功能的完整工作流程

这段代码实现的是选择文件后点击预览按钮,在右侧头像区域显示图片的功能。让我一步步拆解它是如何工作的:


一、HTML 结构分析

关键元素有两个:


<!-- 文件选择框,隐藏的,用户看不到 -->
<input type="file" id="file">
<!-- 预览按钮,用户点击这个触发预览 -->
<input type="button" value="预览" onClick="readFile ()">
<!-- 头像显示区域,id为result,初始为空 -->
<div class="photo" id="result"></div>

布局示意图

360截图20260315212813915.jpg


二、JavaScript 代码逐行详解


//javascript document
function readFile (){
    // 第1步:获取用户选择的文件
    var file = document.getElementById("file").files[0];

第1步:获取文件对象

  • document.getElementById("file"):找到隐藏的文件选择框

  • .files[0]:获取用户选择的第一个文件(因为是单选)

  • 此时 file 变量就是一个 File 对象,包含了文件的所有信息




    // 检查是否为图像文件
    if(!/image\/\w+/.test(file.type))    {
        alert("请确保文件为图像类型");
        return false;
    }

第2步:验证文件类型

  • /image\/\w+/ 是一个正则表达式:

    • image\/:匹配 "image/" 字符串

    • \w+:匹配一个或多个字母、数字、下划线

    • 整体匹配 image/jpegimage/pngimage/gif 等图片 MIME 类型

  • 如果 file.type 不匹配(即不是图片),弹出警告并退出函数




    var reader = new FileReader();
    reader.readAsDataURL(file); //将文件以Data URL形式进行读入页面

第3步:创建 FileReader 并读取文件

  • new FileReader():创建一个文件读取器对象

  • reader.readAsDataURL(file):将文件读取为 Data URL 格式

    • Data URL 的格式:data:image/jpeg;base64,/9j/4AAQSkZJRg...

    • 它把图片的二进制数据转换成 base64 编码的字符串

    • 这个字符串可以直接作为 <img> 的 src 属性使用





    reader.onload = function(e)    {
       var result = document.getElementById("result");
       result.innerHTML = '<img src="'+this.result+'" alt=""/>'; //在页面上显示文件
    }
}

第4步:读取完成后的回调函数

  • reader.onload:当文件读取完成时自动执行这个函数

  • e 是事件对象,但这里直接用 this.result 获取读取结果

  • document.getElementById("result"):找到头像显示区域

  • result.innerHTML = '<img src="'+this.result+'" alt=""/>'

    • 动态创建一个 <img> 标签

    • src 属性设置为刚才读取的 Data URL(包含图片数据)

    • 把这个图片插入到头像区域中显示


三、数据流向图


用户操作                    JavaScript处理                    页面显示
─────────────────────────────────────────────────────────────────
1. 点击"选择头像"按钮
   ↓
   弹出文件选择对话框
   ↓
2. 选择图片文件
   ↓
   file 对象生成
   ├─ name: "avatar.jpg"
   ├─ size: 102400
   └─ type: "image/jpeg"
   ↓
3. 点击"预览"按钮
   → 调用 readFile()
   ↓
4. FileReader 读取图片
   ↓
   转换成 Data URL
   (base64编码)
   ↓
5. reader.onload 触发
   → 获取读取结果
   ↓
6. 动态创建 img 标签
   src = Data URL
   ↓
7. 插入到 #result 元素
   ↓
   ┌─────────┐
   │  图片   │
   │  显示   │
   └─────────┘


四、Data URL 详解

什么是 Data URL?

Data URL 是一种将文件数据直接嵌入到 URL 中的方案,格式为:


data:[<mediatype>][;base64],<data>

例如一个 1x1 像素的红点图片的 Data URL:


data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==

为什么用 Data URL?

  1. 不需要服务器:图片数据都在 URL 里,不依赖网络请求

  2. 即时预览:文件一读完就能显示

  3. 安全性:不会泄露本地文件路径

Data URL 的缺点

  • 比原始文件大约 30%(base64 编码膨胀)

  • 不适合大文件(会生成很长的字符串)


五、代码的执行时机

顺序很重要!


reader.readAsDataURL(file);  // 第1步:开始读取
reader.onload = function() {  // 第2步:设置回调函数
    // 显示图片
}

注意:虽然代码中 onload 写在后面,但实际执行顺序是:

  1. readAsDataURL() 开始读取(异步操作)

  2. 设置 onload 回调

  3. 读取完成后自动调用 onload

如果反过来写:


reader.onload = function() { ... }  // 先设置回调
reader.readAsDataURL(file);         // 再开始读取

这样更合理,但两种写法都能工作。


六、最终效果

执行完成后,HTML 结构变成:


<div class="photo" id="result">
    <img src="data:image/jpeg;base64,/9j/4AAQSkZJRg..." alt="">
</div>

视觉上:用户选择的图片就显示在头像区域了!


七、总结

步骤操作说明
1用户选择文件通过 <input type="file">
2获取 File 对象file = files[0]
3验证文件类型正则检查是否为图片
4创建 FileReadernew FileReader()
5读取为 Data URLreadAsDataURL(file)
6读取完成onload 回调触发
7创建 img 标签src = this.result
8插入到页面result.innerHTML = ...

一句话总结:通过 FileReader 把用户选择的图片转换成 Data URL,然后动态创建 img 标签插入到头像区域,实现本地图片预览。



'+this.result+'为什么是读取的Data URl结果?

没见这个result和前面的reader变量之间有关联啊?


一、代码回顾


var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function(e) {
    var result = document.getElementById("result");
    result.innerHTML = '<img src="'+this.result+'" alt=""/>';
}

您疑惑的是:this.result 中的 result 看起来和上面的 reader 变量没有直接关联,为什么它能取到读取结果?


二、关键点:this 指向谁?

在这个回调函数中,this 指向的是触发这个事件的源对象——也就是 reader 对象本身

验证 this 的指向


reader.onload = function(e) {
    console.log(this === reader);  // true
    console.log(this === e.target); // true(e.target 也指向 reader)
    console.log(this.result === reader.result); // true
}

所以:

  • this === reader

  • this.result === reader.result

这就是为什么可以用 this.result 取到读取结果!


三、可视化理解


// 创建一个 reader 对象
var reader = new FileReader();
// 此时 reader 是空对象,还没有 result 属性
reader.readAsDataURL(file);
// 开始读取,reader.result 还是空的
// 设置回调函数
reader.onload = function(e) {
    // 当读取完成时,reader.result 已经被赋值
    // 这里的 this 就是 reader
    console.log(this.result);  // 就是 reader.result
}

示意图

360截图20260315213422065.jpg

四、为什么可以用 this 而不是 reader

其实用 reader.result 也是完全正确的:


reader.onload = function(e) {
    var result = document.getElementById("result");
    // 两种写法都可以
    result.innerHTML = '<img src="'+reader.result+'" alt=""/>';  // 直接使用 reader
    // 或
    result.innerHTML = '<img src="'+this.result+'" alt=""/>';    // 使用 this
}

两种写法的区别

写法优点缺点
reader.result直观,一看就知道来自 reader如果外部变量名改变,要同步修改
this.result灵活,不依赖外部变量名需要理解 this 的指向

五、实际执行过程分解


// 第1步:创建 reader
var reader = new FileReader();
// reader = { result: undefined }
// 第2步:开始读取
reader.readAsDataURL(file);
// 开始异步操作,reader.result 仍为空
// 第3步:设置回调函数
reader.onload = function(e) {
    // 这个函数现在只是"注册"了,还没执行
    // 函数内部的 this 会在执行时确定
}
// 第4步:读取完成(异步)
// 浏览器自动给 reader.result 赋值为 Data URL
// reader.result = "data:image/jpeg;base64,/9j/4AAQ..."
// 第5步:自动调用回调函数
// 调用时把 reader 作为 this 传入
// 所以函数内部的 this 指向 reader
// 第6步:执行函数体
var result = document.getElementById("result");
result.innerHTML = '<img src="'+this.result+'" alt=""/>';
// 这里的 this.result 就是 reader.result,即 Data URL


六、一个更直观的类比

想象这个过程就像点外卖


// 你点外卖(创建 reader)
var 外卖员 = new 外卖员();
// 你下单(开始读取)
外卖员.取餐(餐厅);
// 你告诉外卖员送到后怎么做(设置回调)
外卖员.送达后 = function() {
    // 这里的 this 就是外卖员自己
    console.log(this.餐品);  // 就是外卖员手里的餐品
}
// 外卖员取到餐后(读取完成)
// 自动调用 送达后 函数,this 指向外卖员

在这个类比中:

  • this === 外卖员

  • this.餐品 === 外卖员手里的餐品(即 reader.result


七、验证方法

您可以自己验证一下:


reader.onload = function(e) {
    console.log('this === reader:', this === reader);  // true
    console.log('this.result === reader.result:', this.result === reader.result);  // true
    console.log('e.target === reader:', e.target === reader);  // true(e.target 也指向 reader)
    
    var result = document.getElementById("result");
    // 三种写法都可以
    result.innerHTML = '<img src="'+this.result+'" alt=""/>';
    // 或
    result.innerHTML = '<img src="'+reader.result+'" alt=""/>';
    // 或
    result.innerHTML = '<img src="'+e.target.result+'" alt=""/>';
}


八、总结

问题答案
this.result 来自哪里?来自 reader.result
为什么 this 指向 reader在回调函数中,this 指向触发事件的对象
可以用 reader.result 吗?完全可以,两种写法等价
哪个写法更好?reader.result 更直观,this.result 更灵活

一句话总结this.result 中的 this 指向 reader 对象,所以 this.result 就是 reader.result,也就是 FileReader 读取文件后存储结果的地方。


标签: