// 单一职能原则 => 代码中一个定义只用于描述一个功能
// => 一个文件的代码组成只用于解决一类问题
// 优点:文件功能独立相互关联引用,但互不干扰,可以快速替换和修改、可以快速复用
// 缺点:调用链长,中途接收开发困难
// vue的容器构建时,页面定义的代码不是最终呈现的DOM
/*
Vue实例添加 template 属性,可以独立定义页面构成模板
vue容器构建步骤:
1.读取容器代码结构 => template
2.渲染代码结构为真实响应式DOM => render
3.将真实响应式DOM写入到页面对应的位置进行展示 => mount(el)
template 构成的模板 最终会替换到 mount(el) 指向元素的内容
示例:
Vue.createApp({,
template:StringDOM | StringEl
}).mount("#app")
+ StringDOM:HTML标签的字符串定义方式
+ StringEl:HTML元素选择器
<div id="app">
<h1>测试template优先级</h1>
</div>
<hr>
<!-- 模板第一种定义方案 -->
<!-- <div id="root" style="display: none;">
<h5>页面root模板-div</h5>
<p>msg:{{ msg }}</p>
<input type="text" v-model="msg">
</div> -->
<!-- 模板第二种定义方案 -->
<!-- <template id="root">
<h5>页面root模板-template</h5>
<p>msg:{{ msg }}</p>
<input type="text" v-model="msg">
</template> -->
<!-- 模板第三种定义方案 -->
<script type="text/x-template" id="root">
<h5>页面root模板-script</h5>
<p>msg:{{ msg }}</p>
<input type="text" v-model="msg">
</script>
<script type="module">
// 单一职能原则 => 代码中一个定义只用于描述一个功能
// => 一个文件的代码组成只用于解决一类问题
// 优点:文件功能独立相互关联引用,但互不干扰,可以快速替换和修改、可以快速复用
// 缺点:调用链长,中途接收开发困难
// vue的容器构建时,页面定义的代码不是最终呈现的DOM
/*
Vue实例添加 template 属性,可以独立定义页面构成模板
vue容器构建步骤:
1.读取容器代码结构 => template
2.渲染代码结构为真实响应式DOM => render
3.将真实响应式DOM写入到页面对应的位置进行展示 => mount(el)
template 构成的模板 最终会替换到 mount(el) 指向元素的内容
示例:
Vue.createApp({,
template:StringDOM | StringEl
}).mount("#app")
+ StringDOM:HTML标签的字符串定义方式
+ StringEl:HTML元素选择器
*/
import { createApp } from "../assets/vue/3.0/vue.esm-browser.js";
createApp({
// template:`
// <p>msg:{{ msg }}</p>
// <input type="text" v-model="msg">
// `,
template:"#root",
data(){
return {
msg:"msg测试数据"
}
}
}).mount("#app")
</script>
2、模板渲染函数(render)
<div id="app"></div>
<script>
// 1、提供页面结构 => template
let htmlTemplate = `
<p>msg:{{ msg }}</p>
<input type="text" v-model="msg">
`;
let data = {
msg:"测试msg"
}
// 1.1 字符串到dom的转换
let domBox = document.createElement("div");
domBox.innerHTML = htmlTemplate;
// console.log(domBox);
let list = domBox.childNodes
console.log(list);
// JS 内存dom虚拟容器盒子
let tempBox = document.createDocumentFragment();
list.forEach(item=>{
// console.log(item,item.cloneNode(true));
// 2、渲染节点 => render
// 递归函数 => vue的语法解析 => 响应式关联
let cloneNode = item.cloneNode(true)
let text = cloneNode.textContent;
let flag = text.match(/{{\s*([^\s]*)\s*}}/);
if(flag!=null){
cloneNode.textContent = text.replace(/{{\s*([^\s]*)\s*}}/,data[flag[1]])
}
tempBox.appendChild( cloneNode )
})
// 3、把转换的DOM节点渲染到页面 => mount(el)
let htmlBox = document.querySelector("#app")
// console.log(htmlBox);
htmlBox.appendChild(tempBox)
</script>
3、虚拟DOM
<body>
<div id="app">
</div>
<script type="module">
import { createApp,h,createVNode } from "../assets/vue/3.0/vue.esm-browser.js";
createApp({
data(){
return {
msg:"测试MSG变量关联"
}
},
render(vm) {
console.log(vm,this);
// console.log(h);
// h 是vue在render函数中提供的用于完成响应式关联的DOM构建工具
// return "<h4>测试数据</h4>"
// return h("h4","render函数模板:"+vm.msg)
return h("div",[
"容器",
h("h4","render函数模板:"+vm.msg),
h("input",{ type:"text",value:vm.msg,onInput:(event)=>{ vm.msg = event.target.value } })
])
},
}).mount("#app")
</script>
<div id="app">
<div>
<p ref="pDom">msg:{{ msg }}</p>
<input type="text" v-model="msg">
<p>info:{{ info }}</p>
<input type="text" v-model="info">
<br><br>
<input type="button" value="销毁" @click="unmountCallback()">
</div>
</div>
<script type="module">
import { createApp } from "../assets/vue/3.0/vue.esm-browser.js";
let app = createApp({
data(){
return {
msg:"msg数据",
info:"info数据"
}
},
methods: {
unmountCallback(){
app.unmount()
}
},
beforeCreate() {
console.group("beforeCreate=====>")
console.log("vue实例构建完成,vue环境构建完成");
console.log("$data:",this.$data); // {}
console.log("msg:",this.msg); // undefined
console.groupEnd();
},
// 应用:在vue项目运行时用于初始化数据的请求(ajax数据加载)-最早的初始化数据加载生命周期钩子函数
// 特殊vue运行环境(SSR):服务端渲染初始数据的加载最好是在created生命周期中完成
// ==> SSR 可以提供更好的 SEO(搜索引擎优化-就是爬虫-不执行css和js)
// ==> SSR 首屏(第一个页面) 效率根高 (一个优秀的知识宣传网站不超过8屏[8个屏幕大小])
created() {
console.group("created=====>")
console.log("运行依赖的加载,响应式功能的构成");
console.log("$data:",this.$data); // Proxy {msg: 'msg数据'}
console.log("msg:",this.msg); // 'msg数据'
console.groupEnd();
},
beforeMount() {
console.group("beforeMount=====>")
console.log("加载和编译模板结构,生成虚拟DOM树(JS对象)=>绑定响应数据=>引入diff算法");
console.log("$el:",this.$el); // null
console.log("$refs.pDom:",this.$refs.pDom); // undefined
console.groupEnd();
},
// 应用:需要基于页面元素进行初始化构建的相关操作,都会在mounted进行调用
// 该构造函数是vue自动化执行的初始方法中的最后一个,且上述生命周期构子函数只会执行一次
mounted() {
console.group("mounted=====>")
console.log("基于虚拟节点(vnode)构建的带有响应式功能的真实DOM树,已完成创建和页面写入");
console.log("$el:",this.$el); // 页面最终容器DOM
console.log("$refs.pDom:",this.$refs.pDom); // 页面最终的元素
console.groupEnd();
},
// 被动监控变量更新后的 vnode操作和DOM更新
beforeUpdate() {
console.group("beforeUpdate=====>")
console.log("数据仓库变量已被修改,DOM尚未更新");
console.log("$data:",this.$data);
console.log("$refs.pDom.textContent:",this.$refs.pDom.textContent);
console.groupEnd();
},
updated() {
console.group("updated=====>")
console.log("基于diff算法的vnode更新完成,同时DOM渲染完成");
console.log("$data:",this.$data);
console.log("$refs.pDom.textContent:",this.$refs.pDom.textContent);
console.groupEnd();
},
// vue3的销毁构造函数
beforeUnmount() {
console.group("beforeUnmount=====>")
console.log("开始销毁");
console.groupEnd();
},
unmounted() {
console.group("unmounted=====>")
console.log("销毁完成");
console.groupEnd();
},
// vue2的销毁构造函数
// beforeDestroy() {
// },
// destroyed() {
// },
});
// setTimeout(() => {
// app.mount("#app")
// }, 5000);
app.mount("#app")
</script>
<div id="app">
<div class="swiper-container" ref="loop">
<div class="swiper-wrapper">
<div class="swiper-slide">slider1</div>
<div class="swiper-slide">slider2</div>
<div class="swiper-slide">slider3</div>
</div>
</div>
<hr>
<pre>请求结果:{{ result }}</pre>
</div>
<script type="module">
import { createApp } from "../assets/vue/3.0/vue.esm-browser.js";
createApp({
data(){
return {
result:{}
}
},
methods: {
initSwiper(){
new Swiper(this.$refs.loop, {
autoplay: 5000,//可选选项,自动滑动
})
},
loadInitData(){
axios.get("http://127.0.0.1:3000/public/user")
.then(( response )=>{
console.log( response.data );
this.result = response.data
})
.catch(()=>{
alert("请求失败")
})
}
},
created() {
this.loadInitData();
},
mounted() {
// 不要在生命周期构子函数中定义大量的逻辑执行代码
// 以方法方式分解功能,通过实例进行调用
// new Swiper(this.$refs.loop, {
// autoplay: 5000,//可选选项,自动滑动
// })
// this.loadInitData();
this.initSwiper();
},
}).mount("#app")
</script>