语法:Object.defineProperty(obj,property,descriptor)
参数一:obj
绑定属性的目标对象
参数二:property
绑定的属性名
参数三:descriptor
属性描述(配置),且此参数本身为一个对象
属性值1:value
设置属性默认值
属性值2:writable
设置属性是否能够修改
属性值3:enumerable
设置属性是否可以枚举,即是否允许遍历
属性值4:configurable
设置属性是否可以删除或编辑
属性值5:get
获取属性的值
属性值6:set
设置属性的值
<script>
let data = {}
Object.defineProperty(data,'name',{
get(){
console.log("调用get方法")
return "可可";
},
set(newValue){
console.log("调用set方法",newValue);
},
})
console.log("data.name:",data.name)
console.log("-------------------------")
data.name = "keke";
console.log("data.name|data[name]:",data.name)
</script>
可以看到新值并没有覆盖原来的值,默认的内置函数,如果输入data.name="珊珊"
便会调用内置的set方法
实现新值覆盖
<script>
let data = {}
let _name = '可可';
Object.defineProperty(data,'name',{
get(){
console.log("调用get方法")
return _name;
},
set(newValue){
_name = newValue;
console.log("调用set方法",newValue);
},
})
console.log("data.name:",data.name)
console.log("-------------------------")
data.name = "keke";
console.log("data.name|data[name]:",data.name)
</script>
输出结果如下
自定义更改新值
<script>
let data= {
name:"可可",
age:20
};
Object.keys(data).forEach(function(e){
console.log(data[e])
resolve(data,e,data[e])
})
function resolve(data,key,value){
Object.defineProperty(data,key,{
set(newValue){
if(value==newValue){
return ;
}
value = newValue;
document.querySelector("#olp").innerHTML=newValue;
console.log("设置",value)
},
get(){
console.log("得到",value)
return value;
}
});
}
</script>
数据变化反应到视图
<script>
data = {
name:"凌霄"
}
function compile(){
let app = document.getElementById("app");
const childNodes = app.childNodes;
childNodes.forEach(function(e){
if(e.nodeType===1){
const attrs = e.attributes;
Array.from(attrs).forEach(attr=>{
if(attr.nodeName === 'v-text'){
e.innerHTML = data[attr.nodeValue];
}
})
}
})
}
compile();
</script>
打印结果:
m-v过程
<script>
data = {
name:"凌霄"
}
function compile(){
let app = document.getElementById("app");
const childNodes = app.childNodes;
childNodes.forEach(function(e){
if(e.nodeType===1){
const attrs = e.attributes;
Array.from(attrs).forEach(attr=>{
if(attr.nodeName === 'v-text'){
e.innerHTML = data[attr.nodeValue];
}
if(attr.nodeName === 'v-model'){
e.value = data[attr.nodeValue];
}
})
}
})
}
compile();
</script>
v-m
<script>
data = {
name:"凌霄"
}
function compile(){
let app = document.getElementById("app");
const childNodes = app.childNodes;
childNodes.forEach(function(e){
if(e.nodeType===1){
const attrs = e.attributes;
Array.from(attrs).forEach(attr=>{
if(attr.nodeName === 'v-text'){
e.innerHTML = data[attr.nodeValue];
}
if(attr.nodeName === 'v-model'){
e.value = data[attr.nodeValue];
e.addEventListener('input',(event)=>{
let newValue = event.target.value;
data[attr.nodeValue] = newValue;
})
}
})
}
})
}
compile();
</script>
<script>
const Dep = {
map:{},
collect(eventName,fn){
if(!this.map[eventName]){
this.map[eventName] = [];
}
//收集事件
this.map[eventName].push(fn)
},
trigger(eventName){
//执行此方法
this.map[eventName].forEach(fn=>fn())
}
}
Dep.collect('han',()=>{
console.log('涵涵今天还在')
})
Dep.collect('端',()=>{
console.log('张张今天还在')
})
Dep.trigger('端')
Dep.trigger('han')
</script>
1.1 什么是SEO
SEO:搜索引擎优化(Search Engine Optimization),
通过各种技术(手段)来确保,我们的Web内容被搜索引擎最大化收录,最大化提高权重,最终带来更多流量。
Vue框架中的服务端渲染
目前我们的vue组件都是在浏览器侧通过js染出来的,所以首次加载时间很慢,如果我们把vue组件交给服务端负责渲染,渲染为完整内容之后直接返给客户端,就可以可以解决既想渲染快,那就需要
1.2 什么是SPA
SPA(single page web application)单页 Web 应用,Web
不再是一张张页面,而是一个整体的应用,一个由路由系统、数据系统、页面(组件)系统等等,组成的应用程序。
我们之前学习的Vue就是SPA中的佼佼者。
SPA 应用广泛用于对SEO要求不高的场景中
服务端渲染(Server Side Render),即:网页是通过服务端渲染生成后输出给客户端。
在SSR中,前端分成2部分:前端客户端、前端服务端 前端服务端,用于发送ajax,获得数据
前端客户端,用于将ajax数据和页面进行渲染,渲染成html页面,并响应给调用程序(浏览器、爬虫)
SPA单页应用程序 | SSR服务器端渲染 | |
---|---|---|
优势 | 1.页面内容在客户端渲染 2. 只关注View层,与后台耦合度低,前后端分离 3.减轻后台渲染画面的压力 | 1.更好的SEO,搜索引擎工具可以直接查看完全渲染的画面 2.更快的内容到达时间 (time-to-content),用户能更快的看到完整渲染的画面 |
劣势 | 1.首屏加载缓慢 2.SEO(搜索引擎优化)不友好 | 1.更多的服务器端负载 2.涉及构建设置和部署的更多要求,需要用Node.js渲染 3.开发条件有限制,一些生命周期将失效 4.一些常用的浏览器API无法使用 |
1.5 什么是Nuxt.js
使用
npx create-nuxt-app <项目名>
总结:
服务端渲染和客户端渲染各自指什么? 有什么特点?
SSR 服务端渲染 网页内容由服务端生成首屏时间短有利于seo
客户端渲染CSR vue、react框架渲染方式 spa都是客户端渲染,首屏渲染时间长不利于seo 。