目录
Model
Control
View
动态渲染视图
模板
MVVM
ViewModel
MVVM简单实现
Observer
Compile
Watcher
首页 后端开发 php教程 MVC、MVVM简单实现方法

MVC、MVVM简单实现方法

Feb 28, 2018 pm 03:40 PM
mvvm 方法 简单

MVC是一种设计模式,它将应用划分为3个部分:数据(模型)、展示层(视图)和用户交互层。结合一下下图,更能理解三者之间的关系。
MVC、MVVM简单实现方法
换句话说,一个事件的发生是这样的过程

  1. 用户和应用交互

  2. 控制器的事件处理器被触发

  3. 控制器从模型中请求数据,并将其交给视图

  4. 视图将数据呈现给用户

模型:用来存放应用的所有数据对象。模型不必知晓视图和控制器的细节,模型只需包含数据及直接和这些数据相关的逻辑。任何事件处理代码、视图模版,以及那些和模型无关的逻辑都应当隔离在模型之外。
视图:视图层是呈现给用户的,用户与之产生交互。在javaScript应用中,视图大都是由html、css和JavaScript模版组成的。除了模版中简单的条件语句之外,视图不应当包含任何其他逻辑。事实上和模型类似,视图也应该从应用的其他部分中解耦出来
控制器:控制器是模型和视图的纽带。控制器从视图获得事件和输入,对它们进行处理,并相应地更新视图。当页面加载时,控制器会给视图添加事件监听,比如监听表单提交和按钮单击。然后当用户和应用产生交互时,控制器中的事件触发器就开始工作。
例如JavaScript框架早期框架backbone就是采用的MVC模式。

上面的例子似乎太过空洞,下面讲一个生活中的例子进行讲解:
1、用户提交一个新的聊天信息
2、控制器的事件处理器被触发
3、控制器创建了一个新的聊天模型
4、然后控制器更新视图
5、用户在聊天窗口看到新的聊天信息
讲了一个生活的例子,我们用代码的方式更加深入了解MVC。

Model

MVC中M表示model,与数据操作和行为相关的逻辑都应当放入模型中。例如我们创建一个Model对象,所有数据的操作都应该都放在这个命名空间中。下面是一些简化的代码,首先创建新模型和实例

var Model = {
    create: function() {
        this.records = {}
        var object = Object.create(this)
        object.prototype = Object.create(this.prototype)
        return object
    }
}
登录后复制

create用于创建一个以Model为原型的对象,然后就是一些包括数据操作的一些函数包括查找,存储

var Model = {
    /*---代码片段--*/
    find: function () {
        return this.records[this.id]
    },
    save: function () {
        this.records[this.id] = this 
    }
}
登录后复制

下面我们就可以使用这个Model了:

user = Model.create()
user.id = 1
user.save()
asset = Model.create()
asset.id = 2
asset.save()
Model.find(1)
=> {id:1}
登录后复制

可以看到我们就已经查找到了这个对象。模型也就是数据的部分我们也就完成了。

Control

下面来讲讲mvc中的控制器。当加载页面的时候,控制器将事件处理程序绑定在视图中,并适时地处理回调,以及和模型必要的对接。下面是控制器的简单例子:

var ToggleView = {
    init: function (view) {
        this.view = $(view)
        this.view.mouseover(this.toggleClass, true)
        this.view.mouseout(this.toggleClass, false)
    },
    this.toggleClass: function () {
        this.view.toggleClass('over', e.data)
    }
}
登录后复制

这样我们就实现了对一个视图的简单控制,鼠标移入元素添加over class,移除就移除over class。然后在添加一些简单的样式例如

    ex:
        .over {color: red}
        p{color: black}

这样控制器就和视图建立起了连接。在MVC中有一个特性就是一个控制器控制一个视图,随着项目体积的增大,就需要一个状态机用于管理这些控制器。先来创建一个状态机
var StateMachine = function() {}
SateMachine.add = function (controller) {
    this.bind('change', function (e, current) {
        if (controller == current) {
            controller.activate()
        } else {
            controller.deactivate()
        }
    })

    controller.active = function () {
        this.trigger('change', controller)
    }
}
// 创建两个控制器
var con1 = {
    activate: funtion() {
        $('#con1').addClass('active')
    },
    deactivate: function () {
        $('#con1').removeClass('active')
    }
}

var con2 = {
    activate: funtion() {
        $('#con2').addClass('active')
    },
    deactivate: function () {
        $('#con2').removeClass('active')
    }
}

// 创建状态机,添加状态
var sm = new StateMachine
sm.add(con1)
sm.add(con2)

// 激活第一个状态
con1.active()
登录后复制

这样就实现了简单的控制器管理,最后我们在添加一些css样式。

#con1, #con2 { display: none }
#con2.active, #con2.active { display: block }
登录后复制

当con1激活的时候样式就发生了变化,也就是视图发生了变化。
控制器也就讲到了这里,下面来看看MVC中的View部分,也就是视图

View

视图是应用的接口,它为用户提供视觉呈现并与用户产生交互。在javaScript种,视图是无逻辑的HTML片段,又应用的控制器来管理,视图处理事件回调以及内嵌数据。简单来说就是在javaScript中写HTML代码,然后将HTML片段插入到HTML页面中,这里讲两种方法:

动态渲染视图

使用document.createElement创建DOM元素,设置他们的内容然后追加到页面中,例如
var views = documents.getElementById('views')
views.innerHTML = '' // 元素清空
var wapper = document.createElement('p')
wrapper.innerText = 'add to views'
views.appendChild(wrapper)
这样就完成了用createElement创建元素,然后添加到HTML页面中。

模板

如果以前有过后端开发经验,那么对模版应该比较熟悉。例如在nodejs中常用的就是ejs,下面是ejs的一个小例子,可以看到的是ejs将javascript直接渲染为HTML
str = '

<%= title %>

'
ejs.render(str, {

title: 'ejs'
登录后复制

});
那么这个渲染后的结果就是

ejs


当然实际中ejs的功能更强大,我们甚至可以在其中加入函数,模板语言是不是觉得跟vue,React的书写方式特别像,我也觉得像。那么view的作用就显而易见了,就是将HTML和javaScript连接起来。剩下一个问题就是在mvc原理图我们看到了视图和模型之间的关系,当模型更改的时候,视图也会跟着更新。那么视图和模型就需要进行绑定,它意味着当记录发生改变时,你的控制器不需要处理视图的更新,因为这些更新是在后台自动完成的。为了将javaScript对象和视图绑定在一起,我们需要设置一个回调函数,当对象的属性发生改变时发送一个更新视图的通知。下面是值发生变化的时候调用的回调函数,当然现在我们可以使用更简单的set,get进行数据的监听,这在我们后面的MVVM将会讲到。

var addChange = function (ob) {
    ob.change = function (callback) {
        if (callback) {
            if (!this._change) this._change = {}
            this._change.push(callback)
        } else {
            if (!this._change) return 
            for (var i = this._change.length - 1; i >= 0; i--) {
                this._change[i].apply(this)
            }
        }
    }
}
登录后复制

我们来看看一个实际的例子

var addChange = function (ob) {
    ob.change = function (callback) {
        if (callback) {
            if (!this._change) this._change = {}
            this._change.push(callback)
        } else {
            if (!this._change) return 
            for (var i = this._change.length - 1; i >= 0; i--) {
                this._change[i].apply(this)
            }
        }
    }
}

var object = {}
object.name = 'Foo'

addChange(object)
object.change(function () {
    console.log('Changed!', this)
    // 更新视图的代码
})
obejct.change()
object.name = 'Bar'
object.change()
登录后复制

这样就实现了执行和触发change事件了。
我相信大家对MVC有了比较深刻的理解,下面来学习MVVM模式。

MVVM

如今主流的web框架基本都采用的是MVVM模式,为什么放弃了MVC模式,转而投向了MVVM模式呢。在之前的MVC中我们提到一个控制器对应一个视图,控制器用状态机进行管理,这里就存在一个问题,如果项目足够大的时候,状态机的代码量就变得非常臃肿,难以维护。还有一个就是性能问题,在MVC中我们大量的操作了DOM,而大量操作DOM会让页面渲染性能降低,加载速度变慢,影响用户体验。最后就是当Model频繁变化的时候,开发者就主动更新View,那么数据的维护就变得困难。世界是懒人创造的,为了减小工作量,节约时间,一个更适合前端开发的架构模式就显得非常重要。这时候MVVM模式在前端中的应用就应运而生。
MVVM让用户界面和逻辑分离更加清晰。下面是MVVM的示意图,可以看到它由Model、ViewModel、View这三个部分组成。
MVC、MVVM简单实现方法
下面分别来讲讲他们的作用

View

View是作为视图模板,用于定义结构、布局。它自己不处理数据,只是将ViewModel中的数据展现出来。此外为了和ViewModel产生关联,那么还需要做的就是数据绑定的声明,指令的声明,事件绑定的声明。这在当今流行的MVVM开发框架中体现的淋淋尽致。在示例图中,我们可以看到ViewModel和View之间是双向绑定,意思就是说ViewModel的变化能够反映到View中,View的变化也能够改变ViewModel的数据值。那如何实现双向绑定呢,例如有这个input元素:

<input type=&#39;text&#39; yg-model=&#39;message&#39;>
登录后复制

随着用户在Input中输入值的变化,在ViewModel中的message也会发生改变,这样就实现了View到ViewModel的单向数据绑定。下面是一些思路:

  1. 扫描看哪些节点有yg-xxx属性

  2. 自动给这些节点加上onchange这种事件

  3. 更新ViewModel中的数据,例如ViewModel.message = xx.innerText

那么ViewModel到View的绑定可以是下面例子:

<p yg-text=&#39;message&#39;></p>
登录后复制

渲染后p中显示的值就是ViewModel中的message变量值。下面是一些思路:

  1. 首先注册ViewModel

  2. 扫描整个DOM Tree 看哪些节点有yg-xxx这中属性

  3. 记录这些被单向绑定的DOM节点和ViewModel之间的隐射关系

  4. 使用innerText,innerHTML = ViewModel.message进行赋值

ViewModel

ViewModel起着连接View和Model的作用,同时用于处理View中的逻辑。在MVC框架中,视图模型通过调用模型中的方法与模型进行交互,然而在MVVM中View和Model并没有直接的关系,在MVVM中,ViewModel从Model获取数据,然后应用到View中。相对MVC的众多的控制器,很明显这种模式更能够轻松管理数据,不至于这么混乱。还有的就是处理View中的事件,例如用户在点击某个按钮的时候,这个行动就会触发ViewModel的行为,进行相应的操作。行为就可能包括更改Model,重新渲染View。

Model

Model 层,对应数据层的域模型,它主要做域模型的同步。通过 Ajax/fetch 等 API 完成客户端和服务端业务 Model 的同步。在层间关系里,它主要用于抽象出 ViewModel 中视图的 Model。

MVVM简单实现

实现效果:

<p id="mvvm">
    <input type="text" v-model="message">
    <p>{{message}}</p>
    <button v-click=&#39;changeMessage&#39;></button>
</p>
<script type="">
    const vm = new MVVM({
        el: '#mvvm',
        methods: {
            changeMessage: function () {
                this.message = 'message has change'
            }
        },
        data: {
            message: 'this is old message'
        }
    })
</script>
登录后复制

这里为了简单,借鉴了Vue的一些方法

Observer

MVVM为我们省去了手动更新视图的步骤,一旦值发生变化,视图就重新渲染,那么就需要对数据的改变就行检测。例如有这么一个例子:

hero = {
    name: 'A'
}
登录后复制

这时候但我们访问hero.name 的时候,就会打印出一些信息:

hero.name 
// I'm A
登录后复制

当我们对hero.name 进行更改的时候,也会打印出一些信息:

hero.name = 'B'
// the name has change
登录后复制

这样我们是不是就实现了数据的观测了呢。
在Angular中实现数据的观测使用的是脏检查,就是在用户进行可能改变ViewModel的操作的时候,对比以前老的ViewModel然后做出改变。
而在Vue中,采取的是数据劫持,就是当数据获取或者设置的时候,会触发Object.defineProperty()。
这里我们采取的是Vue数据观测的方法,简单一些。下面是具体的代码

function observer (obj) {
    let keys = Object.keys(obj)
    if (typeof obj === 'object' && !Array.isArray(obj)) {
        keys.forEach(key => {
            defineReactive(obj, key, obj[key])
        })    
    }
}

function defineReactive (obj, key, val) {
    observer(val)
    Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get: function () {
            console.log('I am A')
            return val
        },
        set: function (newval) {
            console.log('the name has change')
            observer(val)
            val = newval
        }
    }) 
}
登录后复制

把hero带入observe方法中,结果正如先前预料的一样的结果。这样数据的检测也就实现了,然后在通知订阅者。如何通知订阅者呢,我们需要实现一个消息订阅器,维护一个数组用来收集订阅者,数据变动触发notify(),然后订阅者触发update()方法,改善后的代码长这样:

function defineReactive (obj) {
    dep = new Dep()
    Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get: function () {
            console.log('I am A')
            Dep.target || dep.depend()
            return val
        },
        set: function (newval) {
            console.log('the name has change')
            dep.notify()
            observer(val)
            val = newval
        }
    }) 
}

var Dep = function Dep () {
    this.subs = []
}
Dep.prototype.notify = function(){
    var subs = this.subs.slice()
    for (var i = 0, l = subs.length; i < l; i++) {
        subs[i].update()
    }
}
Dep.prototype.addSub = function(sub){
    this.subs.push(sub)
}
Dep.prototype.depend = function(){
    if (Dep.target) {
        Dep.target.addDep(this)
    }
}
登录后复制

这跟Vue源码差不多,就完成了往订阅器里边添加订阅者,和通知订阅者。这里以前我看Vue源码的时候,困扰了很久的问题,就是在get方法中Dep是哪儿来的。这里说一下他是一个全局变量,添加target变量是用于向订阅器中添加订阅者。这里的订阅者是Wacther,Watcher就可以连接视图更新视图。下面是Watcher的一部分代码

Watcher.prototype.get = function(key){
    Dep.target = this
    this.value = obj[key] // 触发get从而向订阅器中添加订阅者
    Dep.target = null // 重置
};
登录后复制

Compile

在讲MVVM概念的时候,在View -> ViewModel的过程中有一个步骤就是在DOM tree中寻找哪个具有yg-xx的元素。这一节就是讲解析模板,让View和ViewModel连接起来。遍历DOM tree是非常消耗性能的,所以会先把节点el转换为文档碎片fragment进行解析编译操作。操作完成后,在将fragment添加到原来的真实DOM节点中。下面是它的代码

function Compile (el) {
    this.el = document.querySelector(el)
    this.fragment = this.init()
    this.compileElement()
}

Compile.prototype.init = function(){
    var fragment = document.createDocumentFragment(), chid 
    while (child.el.firstChild) {
        fragment.appendChild(child)
    }
    return fragment
};

Compile.prototype.compileElement = function(){
    fragment = this.fragment 
    me = this 
    var childNodes = el.childNodes 
    [].slice.call(childNodes).forEach(function (node) {
        var text = node.textContent 
        var reg = /\{\{(.*)\}\}/ // 获取{{}}中的值
        if (reg.test(text)) {
            me.compileText(node, RegExp.$1)
        }

        if (node.childNodes && node.childNodes.length) {
            me.compileElement(node)
        }
    })
}
Compile.prototype.compileText = function (node, vm, exp) {
    updateFn && updateFn(node, vm[exp])
    new Watcher(vm, exp, function (value, oldValue) {
        // 一旦属性值有变化,就会收到通知执行此更新函数,更新视图
        updateFn() && updateFn(node, val)
    })
}
// 更新视图
function updateFn (node, value) {
    node.textContent = value 
}
登录后复制

这样编译fragment就成功了,并且ViewModel中值的改变就能够引起View层的改变。接下来是Watcher的实现,get方法已经讲了,我们来看看其他的方法。

Watcher

Watcher是连接Observer和Compile之间的桥梁。可以看到在Observer中,往订阅器中添加了自己。dep.notice()发生的时候,调用了sub.update(),所以需要一个update()方法,值发生变化后,就能够触发Compile中的回调更新视图。下面是Watcher的具体实现

var Watcher = function Watcher (vm, exp, cb) {
    this.vm = vm 
    this.cb = cb 
    this.exp = exp 
    // 触发getter,向订阅器中添加自己
    this.value = this.get()
}

Watcher.prototype = {
    update: function () {
        this.run()
    },
    addDep: function (dep) {
        dep.addSub(this)
    },
    run: function () {
        var value = this.get()
        var oldVal = this.value 
        if (value !== oldValue) {
            this.value = value 
            this.cb.call(this.vm, value, oldValue) // 执行Compile中的回调
        }
    },
    get: function () {
        Dep.target = this 
        value = this.vm[exp] // 触发getter
        Dep.target = null 
        return value 
    }
}
登录后复制

在上面的代码中Watcher就起到了连接Observer和Compile的作用,值发生改变的时候通知Watcher,然后Watcher调用update方法,因为在Compile中定义的Watcher,所以值发生改变的时候,就会调用Watcher()中的回调,从而更新视图。最重要的部分也就完成了。在加一个MVVM的构造器就ok了。推荐一篇文章自己实现MVVM,这里边讲的更加详细。

相关推荐:

PHP学习MVC框架之路由

TP框架多层MVC用法分析

MVC框架是什么 这里为你解答_实用技巧


以上是MVC、MVVM简单实现方法的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

怎么删除微信好友?删除微信好友的方法 怎么删除微信好友?删除微信好友的方法 Mar 04, 2024 am 11:10 AM

微信是主流的聊天工具之一,我们可以通过微信认识新的朋友,联系老的朋友,维系朋友之间的情谊。正如天下没有不散的宴席,人与人之间的相处难免会发生意见不合的时候。当一个人极其影响你的情绪,或者在相处的时候发现三观不合,没办法再继续沟通,那么我们可能需要删除微信好友的方法。怎么删除微信好友?删除微信好友的方法第一步:在微信主界面轻触【通讯录】;第二步:点击对应要删除的好友,进入【详细资料】;第三步:点击右上角【...】;第四步:点击下方【删除】即可;第五步:了解后页面提示后,点击【删除联系人】即可;温馨

怎么在番茄免费小说app中写小说 分享番茄小说写小说方法教程 怎么在番茄免费小说app中写小说 分享番茄小说写小说方法教程 Mar 28, 2024 pm 12:50 PM

  番茄小说是一款非常热门的小说阅读软件,我们在番茄小说中经常会有新的小说和漫画可以去阅读,每一本小说和漫画都很有意思,很多小伙伴也想着要去写小说来赚取赚取零花钱,在把自己想要写的小说内容编辑成文字,那么我们要怎么样在这里面去写小说呢?小伙伴们都不知道,那就让我们一起到本站本站中花点时间来看写小说的方法介绍吧。分享番茄小说写小说方法教程  1、首先在手机上打开番茄免费小说app,点击个人中心——作家中心  2、跳转到番茄作家助手页面——点击创建新书在小说的结

七彩虹主板怎么进入bios?教你两种方法 七彩虹主板怎么进入bios?教你两种方法 Mar 13, 2024 pm 06:01 PM

  七彩虹主板在中国国内市场享有较高的知名度和市场占有率,但是有些七彩虹主板的用户还不清楚怎么进入bios进行设置呢?针对这一情况,小编专门为大家带来了两种进入七彩虹主板bios的方法,快来试试吧!  方法一:使用u盘启动快捷键直接进入u盘装系统  七彩虹主板一键启动u盘的快捷键是ESC或F11,首先使用黑鲨装机大师制作一个黑鲨U盘启动盘,然后开启电脑,当看到开机画面的时候,连续按下键盘上的ESC或F11键以后将会进入到一个启动项顺序选择的窗口,将光标移动到显示“USB”的地方,然

微信删除的人如何找回(简单教程告诉你如何恢复被删除的联系人) 微信删除的人如何找回(简单教程告诉你如何恢复被删除的联系人) May 01, 2024 pm 12:01 PM

而后悔莫及、人们常常会因为一些原因不小心将某些联系人删除、微信作为一款广泛使用的社交软件。帮助用户解决这一问题,本文将介绍如何通过简单的方法找回被删除的联系人。1.了解微信联系人删除机制这为我们找回被删除的联系人提供了可能性、微信中的联系人删除机制是将其从通讯录中移除,但并未完全删除。2.使用微信内置“通讯录恢复”功能微信提供了“通讯录恢复”节省时间和精力,用户可以通过该功能快速找回之前被删除的联系人,功能。3.进入微信设置页面点击右下角,打开微信应用“我”再点击右上角设置图标、进入设置页面,,

Win11管理员权限获取方法汇总 Win11管理员权限获取方法汇总 Mar 09, 2024 am 08:45 AM

Win11管理员权限获取方法汇总在Windows11操作系统中,管理员权限是非常重要的权限之一,可以让用户对系统进行各种操作。有时候,我们可能需要获取管理员权限来完成一些操作,比如安装软件、修改系统设置等。下面就为大家总结了一些获取Win11管理员权限的方法,希望能帮助到大家。1.使用快捷键在Windows11系统中,可以通过快捷键的方式快速打开命令提

手机版龙蛋孵化方法大揭秘(一步一步教你如何成功孵化手机版龙蛋) 手机版龙蛋孵化方法大揭秘(一步一步教你如何成功孵化手机版龙蛋) May 04, 2024 pm 06:01 PM

手机游戏成为了人们生活中不可或缺的一部分,随着科技的发展。它以其可爱的龙蛋形象和有趣的孵化过程吸引了众多玩家的关注,而其中一款备受瞩目的游戏就是手机版龙蛋。帮助玩家们在游戏中更好地培养和成长自己的小龙,本文将向大家介绍手机版龙蛋的孵化方法。1.选择合适的龙蛋种类玩家需要仔细选择自己喜欢并且适合自己的龙蛋种类,根据游戏中提供的不同种类的龙蛋属性和能力。2.提升孵化机的等级玩家需要通过完成任务和收集道具来提升孵化机的等级,孵化机的等级决定了孵化速度和孵化成功率。3.收集孵化所需的资源玩家需要在游戏中

快速掌握:华为手机开启两个微信账号方法大揭秘! 快速掌握:华为手机开启两个微信账号方法大揭秘! Mar 23, 2024 am 10:42 AM

在当今社会,手机已经成为我们生活中不可或缺的一部分。而微信作为我们日常沟通、工作、生活的重要工具,更是经常被使用。然而,在处理不同事务时可能需要分开两个微信账号,这就要求手机能够支持同时登录两个微信账号。华为手机作为国内知名品牌,很多人使用,那么华为手机开启两个微信账号的方法是怎样的呢?下面就来揭秘一下这个方法。首先,要在华为手机上同时使用两个微信账号,最简

手机字体大小设置方法(轻松调整手机字体大小) 手机字体大小设置方法(轻松调整手机字体大小) May 07, 2024 pm 03:34 PM

字体大小的设置成为了一项重要的个性化需求,随着手机成为人们日常生活的重要工具。以满足不同用户的需求、本文将介绍如何通过简单的操作,提升手机使用体验,调整手机字体大小。为什么需要调整手机字体大小-调整字体大小可以使文字更清晰易读-适合不同年龄段用户的阅读需求-方便视力不佳的用户使用手机系统自带字体大小设置功能-如何进入系统设置界面-在设置界面中找到并进入"显示"选项-找到"字体大小"选项并进行调整第三方应用调整字体大小-下载并安装支持字体大小调整的应用程序-打开应用程序并进入相关设置界面-根据个人

See all articles