jQuery和现在使用vue和React框架的区别
- jQuery实现todo-list
<body>
<div>
<input type="text" name="" id="txt-title">
<button id="btn-submit">submit</button>
</div>
<div>
<ul id="ul-list"></ul>
</div>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script>
var $txtTitle = $('#txt-title')
var $btnSubmit = $('#btn-submit')
var $ulList = $('#ul-list')
$btnSubmit.click(function() {
var txt = $txtTitle.val()
if (!title) {
return
}
var $li = `<li>${txt}</li>`
$ulList.append($li)
$txtTitle.val('')
})
</script>
</body>复制代码
- vue实现todo-list
<body>
<div id="app">
<div>
<input type="text" v-model="title">
<button @click="add">submit</button>
</div>
<div>
<ul>
<li v-for="(item, index) in list" :key="index">{{item}}</li>
</ul>
</div>
</div>
<script src="https://unpkg.com/vue"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
title: ''
},
methods: {
add() {
this.list.push(this.title)
this.title = ''
}
}
})
</script>
</body>复制代码
- jQuery 和框架的区别
(1)数据和视图的分离(解耦:开放封闭原则)
(2)以数据驱动视图(只关心数据变化,DOM操作被封装)
如何理解MVVM
- MVVM框架的三大要素:
(1)响应式:vue如何监听到data的每个属性变化?
(2)模板渲染:vue的模板如何被解析,指令如何处理?
(3)渲染:vue的模板如何被渲染成html?以及渲染过程?
- MVC
(1)M:Model数据
(2)V:View视图、界面
(3)C:Controller控制器、逻辑处理
一般都是view发送命令到控制器,控制器修改model,model再将修改对应到View
- MVVM(MVC微创新)
(1)Model:模板、数据
(2)View:视图、模板(视图和模型是分离的)
(3)ViewModel:连接Model和View
- 关于ViewModel
如何实现MVVM
vue如何实现响应式
(1)关键是理解Object.defineProperty
(2)将data的属性代理到vm上
- 什么是响应式
(1)修改data属性之后,vue立刻监听到
(2)data属性被代理到vm上
- Object.defineProperty(附上:阮一峰老师的具体讲解javascript.ruanyifeng.com/stdlib/attr…)
<script>
var obj = {
name: '老王',
age: '40'
}
console.log(obj.name) // 设置obj.name为静态的值类型
obj.name = '111' // 怎么样能监听到
console.log(obj.name) // 怎么样能监听到
var obj = {}
var name = '张三'
Object.defineProperty(obj, "name", { // 当使用Object.defineProperty后设置的name为一个属性
// 将属性的获取、设置都定义为了一个函数 并可以加入自己的逻辑
get: function () {
console.log('get')
return name
},
set: function (newVal) {
console.log('set')
name = newVal
}
})
obj.name = '111' // 可以监听到
console.log(obj.name) // 可以监听到
</script>复制代码
- 模拟
var vm = new Vue({
el: '#app',
data: {
price: 10,
name: '老王'
}
})
// 模拟上面的vue实例
var vm = {}
var data = {
price: 10,
name: '老王'
}
var key, val
for (key in data) {
// 命中闭包 新建一个函数,保证key的独立作用域
(function (key) { // 把当时的key 保留下来
Object.defineProperty(vm, key, {
get: function() {
console.log('get') // 监听
return data[key]
},
set: function(newVal) {
console.log('set') // 监听
data[key] = newVal
}
})
})(key)
}复制代码
vue如何解析模板
- 模板是什么?
<div id="app">
<div>
<input type="text" v-model="title">
<button @click="add">submit</button>
</div>
<div>
<ul>
<li v-for="(item, index) in list" :key="index">{{item}}</li>
</ul>
</div>
</div>复制代码
(1)本质:字符串
(2)有逻辑: 如v-if v-for等
(3)与html格式很像,但又很大的区别
(4)最终还是要转换html显示:1、模板最终必须转换成JS代码,因为有逻辑(v-if、v-for),必须用JS才能实现(图灵完备);2、转换为html渲染页面,必须用JS才能实现;3、模板最终转换成一个JS函数(render函数)
- render函数(模板中所有的信息)
(1)模板中所有信息都包含在了render函数中
(2)this即vm
(3)price 即this.price即vm.price,即data中的price
(4)_c即this._c即vm._c
<body>
<div id="app">
<p>{{price}}</p>
</div>
<script>
var vm = new Vue({
el: '#app',
data: {
price: 100
}
})
function render() {
with(this) { // this 就是 vm
return _c(
'div',
{
attrs: {'id': 'app'}
},
[
_c('p', [_v(_s(price))])
]
)
}
}
function render1() {
return vm._c(
'div',
{
attrs: {'id': 'app'}
},
[
vm._c('p', [vm._v(vm._s(vm.price))])
]
)
}
</script>
</body>复制代码
<body>
<div id="app">
<div>
<input v-model="title">
<button v-on:click="add">submit</button>
</div>
<div>
<ul>
<li v-for="item in list">{{item}}</li>
</ul>
</div>
</div>
<script type="text/javascript">
// data 独立
var data = {
title: '',
list: []
}
// 初始化 Vue 实例
var vm = new Vue({
el: '#app',
data: data,
methods: {
add: function () {
this.list.push(this.title)
this.title = ''
}
}
})
// render 函数
with(this){ // this 就是 vm
return _c(
'div',
{
attrs:{"id":"app"}
},
[
_c(
'div',
[
_c(
'input',
{
directives:[
{
name:"model",
rawName:"v-model",
value:(title),
expression:"title"
}
],
domProps:{
"value":(title)
},
on:{
"input":function($event){
if($event.target.composing)return;
title=$event.target.value
}
}
}
),
_v(" "),
_c(
'button',
{
on:{
"click":add
}
},
[_v("submit")]
)
]
),
_v(" "),
_c('div',
[
_c(
'ul',
_l((list),function(item){return _c('li',[_v(_s(item))])})
)
]
)
]
)
}
</script>
</body>复制代码
- render函数-with的用法(vue用到,不推荐日常使用)
var obj = {
name: '老王',
age: '40',
getAddress: function() {
alert('1111')
}
}
// 不用with
function fn() {
alert(obj.name)
alert(obj.age)
obj.getAddress()
}
fn()
// 使用with 可读性不高
function fn1() {
with(obj) {
alert(name)
alert(age)
getAddress()
}
}
fn1()复制代码
- render函数与vdom(render函数返回的就是vdom)
(1)updateComponent中实现了vdom的patch
(2)页面首次渲染执行updateComponent(把vnode渲染到容器中)
(3)data中每次修改属性,都会执行updateCompoent
介绍vue的实现流程
- 解析模板成render函数
(1)with的用法
(2)模板中的所有信息都被render函数包含
(3)模板中用到的data中的属性,都变成了JS变量
(4)模板中的v-model v-for v-on 都变成了JS逻辑
(5)render函数返回vnode
- 响应式开始监听
(1)Object.defineProperty
(2)将data的属性代理到vm上
- 首次渲染,显示页面,且绑定依赖
(1)初次渲染,执行updateComponent,执行vm._render()
(2)执行render函数,会访问到vm.list和vm.title(data变量)
(3)会被响应式的get方法监听到
为什么要监听get,直接监听set不行吗?
data中有很多属性,有些被用到,有些可能不被用到;被用到的会走到get,不被用到的不会走到get;未走到get中的属性,set的时候我们也无需关心;避免不必要的重复渲染
(4)执行updateComponent,会走到vdom的patch方法
(5)patch 将vnode渲染成DOM,初次渲染完成
- data属性变化,触发render
(1)修改属性,被响应式的set监听到
(2)set中执行updateComponent
(3)updateComponent重新执行vm._render()
(4)生成vnode和prevVnode,通过patch进行对比
(5)渲染到html中