VUEJS学习网址:https://cn.vuejs.org/
此文章是用来记录自己的学习和实践心得。
关注点:父子组件之间的通信
看图说话:
Pass Props
- 子组件本身与父组件是孤立的,通过子组件中显示声明的props属性,接收父组件数据;
- 父组件的数据更新时,子组件的prop会跟着更新;
- 此数据流动是单向的(看着);
Emit Events
- 子组件使用$.emit(fn)向外抛出自己的内部触发的事件;
- 父组件是否监听?如果父组件需要监听,使用
v-on
绑定监听,触发对应事件;
以上为通用语,具体分析
- 子组件可以接收一个字符串,在子组件内部可以用{{label}}使用
<v-input label="姓名">v-input>
- 子组件可以接收动态参数
<input v-model="msg" /> <v-profile :message="msg">v-profile>
子组件接收到数据之后想处理一下不小心改了怎么办?
- 给prop创建一个副本(建议深拷贝),处理副本,不动prop;
父组件的数据改变后,子组件的prop会自动更新,但是这个prop的副本不会啊?
- 使用watch监听这个prop,改变时更新副本;
子组件的prop副本改变了想要通知父组件怎么办?
- 使用watch监听这个副本,改变时向外抛出自己的内部触发的事件;
(添加)父组件的prop改变,但是不想通知子组件怎么办?
- 使用.once显式指定单次绑定
。。。
其实以上???在2.3有了更好的方法,之前的就是看看。
.sync修饰符
***父组件******子组件*** $.emit('update:message',newValue)
(9-21)补充:注释还是建议使用data或compute属性,而不是直接修改prop
子组件想要触发父组件可以emit(父组件需要监听才会触发),父组件触发子组件事件呢?
- 通过在引用的子组件上使用ref属性实现父组件调用子组件的方法以及属性
但是!$refs
只在组件渲染完成后才填充,并且它是非响应式的。它仅仅作为一个直接访问子组件的应急方案——应当避免在模版或计算属性中使用 $refs
。
关注点:非父子组件之间的通信
使用空的vue实例作为中央事件总线
var bus = new Vue(); // 触发组件 A 中的事件 bus.$emit('id-selected', 1) // 在组件 B 创建的钩子中监听事件 bus.$on('id-selected', function (id) { // ... })
考虑vuex
(2018-07-28)注意到了$attrs和¥listeners,用于在多层嵌套中交互,见文档
关注点:在组件中使用slot
首先,在父组件中给子组件标签中间放置内容是无效的。然后slot出场。
白话版本:
匿名slot:
slot标签存在与子组件template中;
子组件在父组件中使用的时候,子组件标签中的结构会在编译后替换子组件的slot标签;
如果子组件中没有slot,则父组件中子组件标签中的内容会消失;
具名slot:
顾名思义,是具有name属性的slot标签;并有匿名组件的特性(以上);
子组件在父组件中使用的时候,子组件中的结构中会有某些标签拥有slot属性并赋值,这些会在编译后替换子组件的相应slot标签;
一句话解释:主要的内容是写在父组件中的子组件标签中,编译后插入子组件的相应位置
讲真,说到这里我自己都不明白要slot干嘛。
官方讲解入口
官方给了个布局的例子:
<div class="container"> <header> <slot name="header">slot> header> <main> <slot>slot> main> <footer> <slot name="footer">slot> footer> div>
这里可能是一个页面标题
主要内容的一个段落。
另一个主要段落。
这里有一些联系信息
但是好像也没什么好推荐的。(个人看法)
再想想:
子组件的template中至少有一个slot标签,slot标签中的内容是default content。什么场景能用到呢?我想到了刚刚写的表格数据筛选,当时用的是v-if,v-else。如果改成slot呢。。。想到slot属性值需要动态传餐,原来写在子组件内部的过滤过程要搬出来放到父组件中执行,然后把执行好的数据塞给子组件的prop。。。
再理一次:
我在子组件的template中设置两个slot
各种展现数据的结构都放这里
没有相关数据
父组件中设置
...
关键就是slot属性动态赋值的问题。。。走不通,脑洞大了按下不说了
作用域插槽
语法:
...
——————这个官网例子我是好半天才明白
{{ props.text }}
以上的template中的props其实和子组件的props属性是相同的,子组件传递了什么prop,它就接收什么,像是下边的传了个text
v-for="item in items"
:text="item.text">
我看了很长很长时间,为什么要这么拐个弯呢。。。
————一夜过后—————
这样内容更灵活:数据是相同的(父组件提供数据),子组件负责了循环(添加逻辑),父组件引用子组件时插入的作用域插槽的模板决定了(展示的形式)!这分工!!!点个赞!!!
我修改了一下自己的table然后页面展示了个空白。之后发现问题出在子组件往外传数据的时候变量名不能用"name"。修改掉。2017-07-14:使用index也不行。。。
2017-07-15:在实际使用的时候发现复用性不强。感觉父子组件之间声明式props传递数据的方式使增强复用性变得困难。
关注点:动态组件使用
- 通过使用保留的
元素,动态地绑定到它的 is
特性,我们让多个组件可以使用同一个挂载点,并动态切换:很适用于制作Tab类的效果
- 在methods属性中定义一个函数修改currentView即可。
- 视情况可以配合 keep-alive 避免重新渲染
- 在子组件上放置activated钩子做切换时的工作:
done()
//放到钩子最后,表示执行工作完毕,可以切换组件,配合keep-alive使用,activated钩子只执行一次
- 子组件接收数据和以往相同,只是这一次都写在了component中,只是如此的话,每个子组件都需要有这些接口(prop)
暂时说到这里,突然得回头看一下react,没时间了,回头会继续。
以上的满基础的(我是新手),有什么不对的求指出,感谢!!!
添加:
关注点:组件间的循环引用
使用全局注册的时候没有问题(框架自行解决)
如果是模块引用(我都是这样的),需要在第一次循环的子组件上声明
beforeCreate: function () {
this.$options.components.TreeFolderContents = require('./tree-folder-contents.vue')
}
自己模仿的示例
treeFolder
folder.name:{{folder.name}}
:children="folder.children"
v-show="folder.show"
/>
treeFolderContent
child.name:{{child.name}}
:folders="child.children"
v-show="child.show"
/>
引用方式
小点tip:
- 低开销的静态组件使用v-once(2017-07-15修改,之前误写成v-on):尽管在 Vue 中渲染 HTML 很快,不过当组件中包含大量静态内容时,可以考虑使用
v-once
将渲染结果缓存起来;
关注点:关于过滤器
vue1.x版本中有很多系统自带的过滤器,在vue2.x版本中都没有了。
- 对于删除掉的那些过滤器可以使用Vue.filter()在全局注册自定义相同功能。必须放在Vue实例化前面。
- 或是使用filters在示例内部注册
- 或是使用Array的新语法filter和computed属性先处理数据返回新的data
2017-07-15
关注点:组件生命周期
看图说话:
-
- beforeCreated:声明------创建实例,但是实例并未创建的阶段,这时候关于Vue实例的属性和方法等都还没有读取到。这是Vuejs实例周期中的第一个阶段,在DOM展示出来(mounted)还有一段时间,我们可以在这里添加loading,增加用户体验。例如:document.body.appendChild(loading);
- created:实例已经创建好了,读到了data(observe data)和自带的事件(Init Event),此时在钩子中运行console.log(this)查看输出。这时候我们可以做一些异步请求,例如请求一些服务器上的数据等。
- 这个Vue实例有el属性吗?如果没有,使用.$mounted("#app")使组件在mounted阶段挂载到#app下;如果有,直接在mounted阶段挂载到#app下;
- 这个Vue实例有template吗?如果有,把template编译成render函数(render函数构造虚拟DOM);如果没有,将el的outerHTML(包括el本身)当做template编译成render函数;
- beforeMounted:不知道这时候干什么好
- mounted:此时,使用vue生成的DOM结构将代替el,可以操作新的#app的DOM结构了,此时,在beforeCreated阶段添加的loading可以消失了;(在这里,我最开始写的是document.body.removeChild(loading);然而并没有什么用,只能给loading加上类名重新选定删除,以下是loading代码。如果是我JS不精造成的问题,请指出!!!):::::::::::20180430:注意
mounted
不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted。OK,问题解决。
-
DOM展现给用户后,用户操作(v-on)引发data change。但是这时候并不是直接操作DOM,而是操作虚拟dom(个人理解:由vue-loader将vue组件文件中的代码解析成了javascript,(render的过程)在用户操作的时候,最先操作这些伪DOM(js操作),然后在re-render成真正的DOM。再此,也总结出vue的一大特点:data和dom并不是直接通讯,而是通过虚拟dom)。这里又牵扯出了数据驱动。。。看图。。。先看看,等等换成新的关注点吧(>.<)
- beforeUpdata:数据已更新,但是虚拟 DOM 重新渲染和打补丁之前触发,此时还可以对data进行操作,此时的data修改并不会触发重渲染(完成你的自定义操作一起渲染)。官网上有一句:该钩子在服务器端渲染期间不被调用。没有接触服务器端渲染,不谈。
- re-render
- updated:此时DOM已经更新了(mounted)
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。(官网原文,我觉得记着就好)
该钩子在服务器端渲染期间不被调用。
- 如果调用了vm.$destroy()(将new Vue({})赋值给变量vm),会先触发beforeDestroy钩子,此时,还是可以操作实例;destroyed钩子紧接着被调用。。。就将所有的watcher,components,listeners删除(此时请再看一眼数据驱动原理图)。之后我又console.log(vm),在控制台上还是能够访问到这个实例Vue$3(怎么命名的啊),换言之,这个实例只是回到了beforeCreated阶段。已经渲染出来的DOM,如果依赖data和init event则会消失,不依赖的会留下。
//用Javascript代码表示DOM节点的伪代码
Let domNode = {
tag: 'ul'
attributes: { id: 'myId' }
children: [
//这里是 li
]
};
var loading = document.createElement("div");
loading.style.width = "1000px";
loading.style.height = "1000px";
loading.className = 'loading';
loading.style.backgroundColor = "#000";
数据驱动原理
关注点:表格展示示例
链接:
- 纯展示版
- 带功能板(呵呵呵,现在只有删除功能,完善中)
2017-07-17
关注点:动画
会有 6 个(CSS)类名在 enter/leave 的过渡中切换
-
v-enter
: 定义进入过渡的开始状态。在元素被插入时生效,在下一个帧移除。
-
v-enter-active
: 定义过渡的状态。在元素整个过渡过程中作用,在元素被插入时生效,在 transition/animation
完成之后移除。 这个类可以被用来定义过渡的过程时间,延迟和曲线函数。
-
v-enter-to
: 2.1.8版及以上 定义进入过渡的结束状态。在元素被插入一帧后生效(于此同时 v-enter
被删除),在 transition/animation
完成之后移除。
-
v-leave
: 定义离开过渡的开始状态。在离开过渡被触发时生效,在下一个帧移除。
-
v-leave-active
: 定义过渡的状态。在元素整个过渡过程中作用,在离开过渡被触发后立即生效,在 transition/animation
完成之后移除。 这个类可以被用来定义过渡的过程时间,延迟和曲线函数。
-
v-leave-to
: 2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发一帧后生效(于此同时 v-leave
被删除),在 transition/animation
完成之后移除。
看概念并不难,直接说我跳过的坑:
css过渡
- 如果设置了v-enter-to,过渡的是v-enter到v-enter-to,如果没有,就是v-enter到你加入动画之前的最初样式,同理v-leave-to
- 自定类名的时候可以使用name属性重置v前缀
css动画 顾名思义,是动画 animation 。
搭配animate.css一起使用。可以通过以下特性来自定义过渡类名:他们的优先级高于普通的类名
enter-class
enter-active-class
enter-to-class
(>= 2.1.8 only)
leave-class
leave-active-class
leave-to-class
(>= 2.1.8 only)
关注点:方法事件处理器 methods
- 在内联方法中传入特殊变量$event,可以在methods中定义的该方法中访问原生事件对象。
- 在事件处理程序中调用
event.preventDefault()
或 event.stopPropagation()
是非常常见的需求。尽管我们可以在 methods 中轻松实现这点,但更好的方式是:methods 只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。(原文)
......
methods: {
warn: function (message, event) {
// 现在我们可以访问原生事件对象
if (event) event.preventDefault()
alert(message)
}
}
关注点:事件修饰符
.enter
.tab
.delete (捕获 “删除” 和 “退格” 键)
.esc
.space
.up
.down
.left
.right
自定义键值修饰符
Vue.config.keyCodes.f1 = 112
鼠标或键盘事件监听
.ctrl
.alt
.shift
.meta
关注点:命名视图
https://jsfiddle.net/posva/6du90epg/
关注点:v-once 与 keep-alive
今天把自己写的心得又读了一遍,对v-once 和keep-alive有点迷惑
v-once只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。
keep-alive包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
今天11月30日,因为一些原因我有2个月没有注意“vuejs”,就这样它悄悄地改变了。。。
纸上得来终觉浅,希望有机会去实践。
实践来了。
2018.1.15
工作告一个段落了,使用公司的接口将新的webApp项目改成了vuejs项目。不是每个页面都重新写了,时间也是不允许的吧。
实现:vue-router,vuex,vue-resourse,selected,下拉加载,输入框和select等。
地址:*********************老大说放公司代码属于侵权。。。
不会再新增关于vue的新随笔,就这一篇,不断的补充,感觉也挺好。(我又加了一个关于框架的。。。)
关注点:watch
watch用来监控某个变化的属性,然后执行方法。在我以往的使用中,只有该监控的属性发生变化时才会触发方法。
- 若果想要初始时就执行这个方法,需要传入新的属性immediate,而之前的方法写到handler中,语法格式如watch: { XXXX: { handler(arg1,arg2,...) { ...},immediate: Bealoon} }。
- 若想监控到对象某个属性的变化(Vue 不能检测到对象属性的添加或删除),以往我是直接给整个对象重新赋值,但是实际上可以通过watcher的deep属性做深层监控,语法同上一条,deep取值为Bealoon。
- watch请尽量写在使用的组件中,监听对象也是组件内有效的,而不是在全局声明一个watch---这样你可能在不想触发的时候触发它。
2018-08-01 在项目中使用vue有半年了,这半年来项目不断,也算是用vue‘摸爬滚打’了,但是总觉得浅。想的用的都很表面,只是‘能跑通’罢了。挫败。
转载于:https://www.cnblogs.com/Merrys/p/7112625.html