VUE问题积累
1、组件三种挂载方式
- 自动挂载
var app3 = new Vue({
el: '#app-3',
data: {
seen: true
}
})
- 手动挂载
// 可以实现延迟按需挂载
<div id="app"> {{name}} </div>
<button onclick="test()">挂载</button>
<script>
var obj= {name: '张三'}
var vm = new Vue({
data: obj
})
function test() {
vm.$mount("#app");
}
// Vue.extend()创建没有挂载的的子类,可以使用该子累创建多个实例
var app= Vue.extend({
template: '<p>{{message}}</p>',
data: function () {
return {
message: 'message'
}
}
})
new app().$mount('#app') // 创建 app实例,并挂载到一个元素上
2、路由传递参数的方式
<p>
<!-- query要用path来引入,params要用name来引入,故不能写为 :to="{path:'/login',params: {isLogin: true}} -->
<!-- 跳转路由时用this.$router: this.$router.push({name:"login",params:{isLogin:true}});this.$router.push({path: '/login', query: {isLogin : true}}); -->
<!-- 接收参数时用this.$route: this.$route.query.isLogin 和 this.$route.params.isLogin; -->
<router-link :to="{name:'login',params: {isLogin: true}}">亲,请登录</router-link>
<router-link :to="{name:'login',params: {isLogin: false}}">免费注册</router-link>
</p>
<!-- 路由出口, 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
3、render:h=>h(App)的理解
render:h=>h(App)是ES6中的箭头函数写法,等价于render:function(h){return h(App);}.
1.箭头函数中的this是 指向 包裹this所在函数外面的对象上。
2.h是creatElement的别名,vue生态系统的通用管理
3.template:‘<app/>’,components:{App}配合使用与单独使用render:h=>h(App)会达到同样的效果
前者识别<template>标签,后者直接解析template下的id为app的div(忽略template的存在)
new Vue({
el: '#app', // 相当于 new Vue({}).$mount('#app');
template: '<App/>', // 1、可以通过在 #app 内加入<app></app>替代 2、或者 通过 render: h => h(App) 渲染一个视图,然后提供给el挂载
components: { // vue2中可以通过 render: h => h(App) 渲染一个视图,然后提供给el挂载
App
}
});
4、Vue.nextTick()的理解
与DOM相关操作写在该函数回调中,确保DOM已渲染
nextTick的由来:
由于VUE的数据驱动视图更新,是异步的,即修改数据的当下,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。
nextTick的触发时机:
在同一事件循环中的数据变化后,DOM完成更新,立即执行nextTick(callback)内的回调。
应用场景:
需要在视图更新之后,基于新的视图进行操作。
- 在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中。原因是什么呢,原因是在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题 。
- 在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。
简单总结事件循环:
同步代码执行 -> 查找异步队列,推入执行栈,执行callback1[事件循环1] ->查找异步队列,推入执行栈,执行callback2[事件循环2]...即每个异步callback,最终都会形成自己独立的一个事件循环。结合nextTick的由来,可以推出每个事件循环中,nextTick触发的时机:
5、动态属性添加
https://cn.vuejs.org/v2/guide...
受现代 JavaScript 的限制 (以及废弃 Object.observe),Vue 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。例如:
var vm = new Vue({
data:{
a:1
}
})
// `vm.a` 是响应的
vm.b = 2
// `vm.b` 是非响应的
Vue 不允许在已经创建的实例上动态添加新的根级响应式属性 (root-level reactive property)。然而它可以使用 Vue.set(object, key, value) 方法将响应属性添加到嵌套的对象上:
Vue.set(vm.someObject, 'b', 2)
您还可以使用 vm.$set 实例方法,这也是全局 Vue.set 方法的别名:
this.$set(this.someObject,'b',2)
有时你想向已有对象上添加一些属性,例如使用 Object.assign() 或 _.extend() 方法来添加属性。但是,添加到对象上的新属性不会触发更新。在这种情况下可以创建一个新的对象,让它包含原对象的属性和新的属性:
// 代替 `Object.assign(this.someObject, { a: 1, b: 2 })`
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
6、样式渗透到子组件
你可以在一个组件中同时使用有作用域和无作用域的样式:
深度作用选择器 https://vue-loader.vuejs.org/...
<style>
/* 全局样式 */
</style>
<style scoped>
/* 本地样式 */
</style>
子组件的根元素:使用 scoped 后,父组件的样式将不会渗透到子组件中。不过一个子组件的根节点会同时受其父组件有作用域的 CSS 和子组件有作用域的 CSS 的影响。这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式。
深度作用选择器:如果你希望 scoped 样式中的一个选择器能够作用得“更深”,例如影响子组件,你可以使用 >>> 操作符:
<style scoped>
.a >>> .b { /* ... */ }
</style>
// 上述代码将会编译成:
.a[data-v-f3f3eg9] .b { /* ... */ }
有些像 Sass 之类的预处理器无法正确解析 >>>。这种情况下你可以使用 /deep/ 操作符取而代之——这是一个 >>> 的别名,同样可以正常工作。
7、路由控制title及权限
import Vue from 'vue';
import Router from 'vue-router';
import store from 'src/vuex/store.js';
Vue.use(Router);
const router = new Router({
routes: [
{
path: '/login', /* 登录界面 */
name: 'login',
component: login/* ,hidden: true, // 自定义属性,在组件中可以通过 this.$route.hidden 获取值 */
},
{
path: '/sysSetting', /* 首页 */
component: sysSetting,
name: 'sysSetting', /* this.$route.matched.filter(item => item.name) */
meta: {
keepAlive: false, /* 用于在 <keep-alive> 中使用,判断是否需要进行缓存 */
auth: true, /* 自定义属性,用于判断是否进行校验,在router.beforeEach中使用 */
title: '系统设置' /* 可以通过$route.meta.title 后取当前的描述信息、菜单信息 */
}
},
{
path: '*', /* 默认跳转到登录界面 */
redirect: {path: '/sysSetting'}
}
]
});
router.beforeEach((to, from, next) => {// 注册一个全局前置守卫
if (to.meta.title) { // 路由发生变化修改页面title
document.title = to.meta.title;
}
if (to.matched.some(m => m.meta.auth)) {// 判断是否需要校验
if (store.state.isLogin) {// 获取
next();// 校验通过,正常跳转到你设置好的页面
} else {
next({// 校验失败,跳转至登录界面
path: '/login',
query: {
redirect: to.fullPath
}// 将跳转的路由path作为参数,用于在登录成功后获取并跳转到该路径
});
}
} else {
next();// 不需要校验,直接跳转
}
});
export default router;
8、嵌套路由及命名视图
https://router.vuejs.org/zh-c...
9、页面路由进度条
http://hilongjw.github.io/vue...
10、静态资源路径
问题描述:<img v-bind:src="imgUrl"/>
绑定的资源请求失败
<template>
<div class="content"
<!-- 界面中引入 -->
<img v-bind:src="imgUrl"/>
</div>
</template>
// js中设置的路径
<script type="text/ecmascript-6">
export default {
data () {
return {
imgUrl : './logo.png' // 此处路径引入错误
};
}
}
原因分析:在上面代码中文件的路径是相对于项目文件目录的,而网页把根域名作为相对路径的根目录(npm run build 生成),并且所有的文件名后都被添加上了一个随机字符串。结构目录如下如下:
解决办法:图片一类的静态文件,应该放在这个static文件夹下,这个文件夹下的文件(夹)会按照原本的结构放在网站根目录下。这时我们再去使用/static绝对路径,就可以访问这些静态文件了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。