vue 双向绑定原理
- VUE 实现双向数据绑定的原理主要是 Object.defineProperty() 方法重新定义了对象获取属性值(get)和设置属性值(set)并配合发布者(接受输入框中值的变量)-订阅者(输入框)模式来实现的.
- 参考一下这位博主的博文
vue 生命周期
=>
1:new Vue(),创建vue对象,执行beforeCreated,这个时候,数据还没有挂载呢,只是一个空壳,无法访问到数据和真实的dom,一般不做操作.
2:挂载数据,绑定事件等等,自己声明的数据和事件,这里可以修改变量的值通过调用created函数来修改.
3:找实例或者组件对应的模板,编译模板为虚拟dom放入到render函数中准备渲染.可以执行beforeMount钩子函数(创建好虚拟dom,可以修改数据).
4:开始render,渲染出真实dom,然后执行mounted钩子函数(组件已经出现在页面中,数据、真实dom都已经处理好了,事件都已经挂载好了,可以在这里操作真实dom等事情).
5:当组件或实例的数据更改之后,会立即执行beforeUpdate(vue的虚拟dom机制会重新构建虚拟dom与上一次的虚拟dom树利用diff算法进行对比之后重新渲染,一般不做什么事儿).
6:当更新完成后,执行updated,数据已经更改完成,dom也重新render完成,可以操作更新后的虚拟dom.
7:当经过某种途径调用$destroy方法后,立即执行beforeDestroy,一般在这里做一些善后工作,例如清除计时器、清除非指令绑定的事件等等.
8:组件的数据绑定、监听...去掉后只剩下dom空壳,这个时候,执行destroyed,在这里做善后工作也可以.
url 从输入到渲染完成经历了哪些过程
=>
1.输入网址;发送到DNS服务器,
2.并获取域名对应的web服务器对应的ip地址;
3.与web服务器建立TCP连接;浏览器向web服务器发送http请求;
4.web服务器响应请求,并返回指定url的数据;
5.浏览器下载web服务器返回的数据及解析html源文件;生成DOM树,解析css和js,渲染页面,直至显示完成;
vue 脚手架 3.0 和 2.0 按需加载 elementui 组件
=>
1:npm install babel-plugin-component -D
2:babel.config.js 或者 .babelrc中添加如下代码(vue-cli3.0 默认创建babel.config.js,.babelrc属于vue-cli2.0默认创建在3.0中没有)
3.vue-cli 3.0配置
{
"presets": [["@babel/preset-env", { "modules": false }]],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
npm install @babel/preset-env -D
4.vue-cli 2.0配置
{
"presets": [["es2015", { "modules": false }]],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}
记录一次 vue 预加载 prerender-spa-plugin 插件的使用
1.vue-cli3.0 配置
1. cnpm install prerender-spa-plugin --save (npm安装可能会报错,推荐使用cnpm)
2. vue.config.js加入以下代码
const PrerenderSPAPlugin = require('prerender-spa-plugin');
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer;
const path = require('path');
module.exports = {
configureWebpack: config => {
if (process.env.NODE_ENV !== 'production') return;
return {
plugins: [
new PrerenderSPAPlugin({
// 生成文件的路径,也可以与webpakc打包的一致。
// 下面这句话非常重要!!!
// 这个目录只能有一级,如果目录层次大于一级,在生成的时候不会有任何错误提示,在预渲染的时候只会卡着不动。
staticDir: path.join(__dirname,'dist'),
// 对应自己的路由文件,比如a有参数,就需要写成 /a/param1。
routes: ['/', '/product','/about'],
// 这个很重要,如果没有配置这段,也不会进行预编译
renderer: new Renderer({
inject: {
foo: 'bar'
},
headless: false,
// 在 main.js 中 document.dispatchEvent(new Event('render-event')),两者的事件名称要对应上。
renderAfterDocumentEvent: 'render-event'
})
}),
],
};
}
}
3.main.js添加
new Vue({
router,
store,
render: h => h(App),
mounted () {
document.dispatchEvent(new Event('render-event'))
}
}).$mount('#app')
4.router.js 中设置mode:"history"
5.npm run build 打包dist目录下会新增 product about对应的文件件,里面有生成好的对应路由的html文件,'/'路由下面的会在index.html中
2.vue-cli2.0 配置
1. cnpm install prerender-spa-plugin --save (npm安装可能会报错,推荐使用cnpm)
2.webpack.prod.conf.js增加部分代码
const path = require('path')
const PrerenderSPAPlugin = require('prerender-spa-plugin') //引用插件
const Renderer = PrerenderSPAPlugin.PuppeteerRenderer
const webpackConfig = merge(baseWebpackConfig, {
plugins: [
// vue-cli生成的配置中就已有这个了,不要动
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
},
chunksSortMode: 'dependency'
}),
// 配置PrerenderSPAPlugin
new PrerenderSPAPlugin({
// 生成文件的路径,也可以与webpakc打包的一致。
staticDir: path.join(__dirname, '../dist'),
// 对应自己的路由文件,比如index有参数,就需要写成 /index/param1。
routes: ['/', '/product','/about','/contact','/join','/jzjh'],
// 这个很重要,如果没有配置这段,也不会进行预编译
renderer: new Renderer({
inject: {
foo: 'bar'
},
headless: false,
// 在 main.js 中 document.dispatchEvent(new Event('render-event')),两者的事件名称要对应上。
renderAfterDocumentEvent: 'render-event'
})
})
]
})
3.在main.js中增加
new Vue({
el: '#app',
router,
render: h => h(App),
mounted () {
document.dispatchEvent(new Event('render-event'))
}
})
4.router.js 中设置mode: "history"
5.npm run build 打包dist目录下会新增 product about对应的文件件,里面有生成好的对应路由的html文件,'/'路由下面的会在index.html中
特别提醒
1.vue-cli2.0 和 3.0 的设置大致一致,但有一个很不同
在 3.0 中,设置 staticDir: path.join(dirname,'dist'),
在 2.0 中,设置 staticDir: path.join(dirname,'../dist'),
如果你把 3.0 的 staticDir 设置为 path.join(dirname,'../dist')或> 者把 2.0 的 staticDir 设置为 path.join(dirname,'dist'),运行 > npm run build 都会报错,这要特别注意!!!
2.不管 2.0 还是 3.0 都需要设置 history 模式
3.node 启动本地服务教程 可以本地起一个服务测试一下(安装好后在 dist 目录下 shift + 右键在此处打开命令行 启动服务找到对应的 html 浏览)
vue 过渡实现渐变出现输入框
> html
<button @click="closeLoading">切换</button>
<transition name="slider">
<div v-if="loading">
<input type="text">
</div>
</transition>
>js
export default {
name: 'home',
data() {
return {
loading: false
}
},
methods: {
closeLoading: function() {
this.loading = !this.loading
}
},
}
>css
.slider-enter-active {
transition: all 2s ease;
}
.slider-leave-active {
transition: all 2s cubic-bezier(1, 0.5, 0.8, 1);
}
.slider-enter,
.slider-leave-to {
transform: translateY(50px);
opacity: 0;
}
.slider-leave,
.slider-enter-to {
transform: rotateY(-50px);
opacity: 1;
}
CSS3实现箭头点击旋转效果
.icon-tran {
transform: rotate(0deg);
transition: transform 0.5s ease-in-out;
}
//点击时再加上这个类名
.icon-transition {
transform: rotate(180deg);
}
vue 自定义 ajax 请求后的 loading 框
1.组件(components)下面新建 loading.vue 写好自己的弹窗效果
2.loading.vue 同级下面新建 loading.js
import load from './loading.vue'
import Vue from 'vue'
let LoadingConstructor = Vue.extend(load)
let instance = new LoadingConstructor({
el: document.createElement('div'),
})
instance.show = false
let loading = {
show(options = {}) {
instance.show = true
console.log(options)
if (options) {
document.getElementsByTagName('body')[0].appendChild(instance.$el)
instance.text = options.text
}
},
hide() {
instance.show = false
},
}
export default {
install() {
if (!Vue.$loading) {
Vue.$loading = loading
}
Vue.mixin({
created() {
this.$loading = Vue.$loading
},
})
},
}
3.main.js 下面
import loading from './components/shop/loading'
Vue.use(loading)
4.然后就可以在 axios 或者页面中直接使用了
Vue.$loading.show()
Vue.$loading.hide()
页面平滑滚动
html, body { scroll-behavior:smooth; }