Vue核心技术总结
2020-04-09 17:44:27 4 举报
AI智能生成
vue全家桶 vue vue-router vuex SSR
作者其他创作
大纲/内容
Vue核心知识
实例
实例属性
$el<br>$render //页面重新渲染的时候触发<br>$date<br>$mount<br>$props<br>$options //在此设置data的值是不会生效的。<br><br>$children<br>$root<br>$slots<br>$refs<br>$isServer
实例方法
$watch和实例里的watch属性是一样的。区别是,$watch需要手动注销。<br><br>$on,$emit 事件的接受和触发在同一个实例上才会生效<br>$once事件只执行一次。 <br> <br>$forceUpdate(),强制渲染<br>$set(app.obj, 'a','123') //新增属性a并赋值<br>$delete可以彻底把属性删掉<br><br> vm.$nextTick([callback]) //下一次渲染的时候,执行
$set, $forceUpdate()<br>使用场景
问题
vue实例的data中有一个obj:{},<br>给obj的属性新增属性,值会改变,但是不会重新渲染
原因
因为 vue 无法监听新增的属性,只能监听你修改属性,除非你开始就指定了相关属性,哪怕是 undefined.<br>
解决办法
$forceUpdate()<br>
强制重新渲染
$set()
Vue.set( target, propertyName/index, value )
向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。<br>它必须用于向响应式对象上添加新属性,因为 Vue 无法探测普通的新增属性 (比如 this.myObject.newProperty = 'hi')
https://cn.vuejs.org/v2/api/#Vue-set-target-propertyName-index-value
参考
$set,$delete,$forceUpdate()的使用<br>https://www.jianshu.com/p/7412bea4e720<br>
1.$set给data对象中的变量设置值,比如我在data中定义了一个对象,在使用的时候我想给这个对象赋予一个a的属性,<br> var app = new Vue({<br> el:"#main",<br> template:'<div>{{obj.a}}</div>'<br> data:{<br> obj:{}<br> }<br> })<br> var i=0;<br> i++;<br> app.$set(app.obj,'a',i)<br> 语法糖[vm.$set( target, key, value )]<br> <br> 2、$delete删除对象的属性<br> app.$delete(app.obj,'a')<br><br> 3、$forceUpdate()强行更新vue实例<br> 在data中声明了obj对象,但并没有a的声明<br> setInterval(()=>{<br> var i=0;<br> i++;<br> app.obj.a=i;<br> },1000)<br> console.log(app.obj.a)<br> 但是在页面中并不会显示出a的值,但是a的值在一直改变,console会打印出来,这中方法a的值并没有在data中事先声明,不能显示在页面,如果想显示出来,也可以在声明obj的时候,给a声明一个空值。<br> 在data中声明的对象的属性并没有声明,但是调用了,这是非响应式,不会重新渲染<br> 方法二: <br> 使用app.$forceUpdate(),强行更新vue实例<br> var app = new Vue({<br> el:"#main",<br> template:'<div>{{obj.a}}</div>'<br> data:{<br> obj:{}<br> }<br> }) <br> setInterval(()=>{<br> var i=0;<br> i++;<br> app.$forceUpdate(app.obj,'a',i)<br> },1000)<br> console.log(app.obj.a) <br> $forceUpdate该方法会重新给obj的a属性重新声明,在页面就能显示出来了,但是这种方法不建议使用,如果要使用到a的值,可以先声明一个空值
$nextTick()
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
https://cn.vuejs.org/v2/api/#Vue-nextTick
生命周期
beforeCreate<br>created<br>beforeMount<br>mounted<br>beforeUpdate<br>updated<br>activated<br>deactivated<br>beforeDestroy<br>destroyed<br>errorCaptured<br>
errorCaptured
可以向上冒泡,能够捕获组件自身和子组件中的render异常<br>可以使用在生产环境
数据绑定
:class<br>:style<br>v-html
:class
https://cn.vuejs.org/v2/guide/class-and-style.html
语法
对象语法
<div v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
数组语法
<div v-bind:class="[activeClass, errorClass]"></div>
混合
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
computed和watch
computed
当app里面的任意属性发生变化时,template会重新渲染。当template通过computed方法获取值时,只有computed 监听的属性发生变化时,才会重新调用函数,否则computed会取缓存里面的值; 当template是通过methods里面的方法获取值时,只要app的任意属性发生变化,都会调用函数。所以,template相对于通过methods里面的方法获取值,通过computed获取值性能会更高。
watch
immediate:true
先执行一遍监听,而不用等数据发生变化再监听
deep:true
wacth想监听对象内部属性变化时,可以使用deep:true 或者 换成字符串格式监听:obj.a -> 'obj.a',推荐使用后者
注意
尽可能不要修改wacth和computed的值,避免造成死循环。
原生指令
常用指令<br>
v-bind: 可缩写为:,绑定某个属性<br>v-on 可缩写@,绑定某个事件<br>
v-text,绑定标签的文本,标签内部只能显示绑定的值,不如{{}}灵活<br>v-html,把变量的内容作为html插入节点
v-if,根据值来定义节点,节点不存在,只是被加入或删除,动态增删节点<br>v-if-else 和if结合使用<br>v-else 和if结合使用,最终不符合情况的结果
v-show,赋值bool来,显示/隐藏节点,节点本来存在,只是被隐藏了,其实就是在节点上加display
v-for
v-for='(item,index) in arr'
v-for='(val,key,index) in obj'
:key
v-model
在input上使用
修饰符
.number
.lazy
.trim
其他不常用指令
v-pre
v-cloak
v-once
首次渲染后,即使数据发生变化,也不会被重新渲染。一般用于静态内容展示。
组件
定义
组件定义
components里,用PascalCase形式
使用自定义的组件时,用kebab-case形式
组件定义的data
data必须是function
props
定义时,用PascalCase形式
使用时,用kebab-case形式,这种形式比较规范<br>也可以写PascalCase形式,遵循团队编码规范即可
注意
不能直接修改prop
继承
extend
this.$parent
this.$parent.$options.name <br>this.$parent.data1<br>获取修改父组件的内容,<br>最好不要修改,容易造成逻辑混乱,多层渲染
双向绑定
v-model
高级属性
<slot>插槽
具名插槽 name
作用域插槽 slot-scope
provide 祖先组件<br>inject 子孙组件<br>
render function
render function
name可以是组件名字,也可以是dom节点
props 可以传递attr ref等
render(createElement) {<br> return createElement('name', {props}, [子组件])<br> }<br>
三种写组件方式:
template
render function
jsx
Vue-Router
vue-router的使用
routes
routes
/ 是默认路由
router
router
使用vue-router
Vue.use(VueRouter)
<router-view><br>展示路由的页面
<router-view>
匹配到的路由页面,会展示在router-view里
命名路由
在.vue文件中引入多个<router-view>时可以使用name命名<br><router-view name="aaa"/><br>在routes.js文件中写路由compnents:{default:组件一,aaa:组件二}
Router构建选项
mode:'history'
mode:'history'
默认是hash模式<br>mode:'history'可以去掉#<br>
base
设置基路径<br>跳转后,路由前会加上/base/,不加也可以
linkActiveClass:<br>linkExactActiveClass:'
链接被激活时显示什么样式
scrollBehavior(to, from,savedPosition){}
定义路由跳转时的滚动行为
parseQuery(query){}<br>stringifyQuery(obj){}
处理url中的query
路由项
name
给路由命名
meta
页面元信息<br>保存路由里的一些信息<br>可以通过route.meta获取
children
子路由
路由传参
/:id<br>动态路由
通过this.$route.params.id获得
通过配置<br>props: true<br>获得
id会自动传到Todo组价里
在Todo组件里,通过props可以获取路由传递的id
?a=123<br>url参数
通过this.$route.query获得
路由导航守卫
全局导航守卫(钩子)
router.beforeEach(to, from, next) {}<br>
使用场景:
用户登陆后页面才能显示页面,如果没登陆则跳转到登陆页面
router.beforeResolve(to, from, next) {}<br>
router.afterEach(to, from) {}<br>
路由独享钩子<br>即在路由配置时增加的钩子
beforeEnter(to, from,next){ next() }
<br>
页面路由钩子<br>即组件内钩子
beforeRouteEach (to,from,next){}<br>
在页面创建之前,拿不到this,可以在next()回调中获取
beforeRouteUpdate(to,from, next){}<br>
使用动态路由时,路由切换时触发
用途
可以用这个钩子获取动态路由
beforeRouteLeave(to, from,next)
使用场景
判断是否离开页面<br>比如用户修改表单时,不小心点了额外的链接,弹出提示让用户确认是否要离开,可以避免误操作导致的修改的表单内容丢失
Vuex
如何使用vuex
安装
npm install vuex -S
声明一个简单的store
store.js
引入
引入
import Vuex from 'vuex'
import createStore from './store/store'
Vue.use(Vuex)
const store = createStore()
在应用的入口中注入store
调用
使用、修改store中的state
更合理的store结构<br>&<br>各部分的实现<br>
拆分后的目录
state.js
state.js
把所有初始数据声明到state.js里
getters.js
getters.js
vuex中的getters相当于vue中的computed
用来组装数据,比如从后端的获取的数据不能直接展示在view里,可以用getters进行数据的组装<br>组装的数据在多个页面都要使用,如果写在computed中进行组装,就要进行重复劳动,而且后期不好维护
mutations.js
mutations.js
作用
mutation是专门用于修改state中的数据的<br>
修改state的方法
使用mutation修改
vue 官方推荐,所有的state修改都放到mutation中<br>可以规范数据的修改
在组件中直接修改
在mutation之外修改,但是这种方式不推荐使用
使用this.$store.state修改state
参数
第一个
state
第二个
第二个参数即Payload,它是object类型<br>https://vuex.vuejs.org/zh/guide/mutations.html#%E6%8F%90%E4%BA%A4%E8%BD%BD%E8%8D%B7%EF%BC%88payload%EF%BC%89
action.js
action.js
参数
第一个
store
第二个
Payload
store.js
拆分后的store.js
strict
strict:true 限制在mutation之外对state进行修改
用于开发环境,可以规范大家的代码
在mutation之外修改state会警告
拆分的好处:当action和mutations变多时,拆分到各自的文件中有利于后期维护
如何使用store
state和getters
使用this.$store<br>获取state和getters
使用this.$store
this.$store.state<br>this.$store.getters<br>这种写法太麻烦
使用mapState和mapGetter<br>获取state和getters
引入
mapState()
使用方式
数组
mapState()接受一个数组,数组中的'count'是state.js中的初始数据count<br>适用于同名的情况
对象
mapState()接受一个对象,获取state.js中的初始数据count并把它重命名为counter<br>适用于重命名的情况
方法
适用于需要做一些计算的情况
作用
可以更便捷的使用state的数据
mapGetters
使用方式
和mapState相同
作用
可以更便捷的使用getter中的数据
mutation和action
区别
mutation用于同步修改数据<br>action用于异步修改数据, 比如数据请求时
使用this.$store触发<br>mutation和action
触发mutation
使用this.$store.commit触发mutation
触发action
使用this.$store.dispatch触发action
使用mapMutation和mapAction<br>触发mutation和action
引入
在methods中引入mutation和action方法
调用action方法
作用
可以更便捷的调用mutation和action方法
模块
模块是什么?
Vuex 允许我们将 store 分割成模块(module)。<br>每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
https://vuex.vuejs.org/zh/guide/modules.html#module
声明模块
声明模块a和b
模块的局部状态
mutation和getter的第一个参数
对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象state
getter第三个参数
对于模块内部的 getter,根节点状态会作为第三个参数暴露出来,即rootState<br>使用rootState,可以在模块内部获取全局state
action参数
对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState:
{root:true}的作用
action默认会在当前模块内部寻找mutation,<br>使用{root:true}可以在模块内部调用全局空间的mutation
调用
使用模块中的state
直接使用
在mapstate中使用
调用模块中的getter
在mapGetter中调用
调用模块中的action
调用局部action
命名空间
namespaced: true
可以在不同的模块中使用相同的变量名、方法名
动态注册模块
动态注册一个模块c
热更替<br>hotUpdate<br>
热更替
作用
当修改了state时,不使用热更替的话,页面会刷新<br>使用热更替,修改的内容会直接更新到页面上,不会刷新页面
一些其他的API<br>和配置
store.watch
watch(fn: Function, callback: Function, options?: Object): Function<br>响应式地侦听 fn 的返回值,当值改变时调用回调函数。fn 接收 store 的 state 作为第一个参数,其 getter 作为第二个参数。最后接收一个可选的对象参数表示 Vue 的 vm.$watch 方法的参数。<br><br>要停止侦听,调用此方法返回的函数即可停止侦听。<br>
https://vuex.vuejs.org/zh/api/#watch
示例
监听state中值的变化
store.subscribe
subscribe(handler: Function): Function<br>订阅 store 的 mutation。handler 会在每个 mutation 完成后调用,接收 mutation 和经过 mutation 后的状态作为参数:
https://vuex.vuejs.org/zh/api/#subscribe
示例
监听mutation的调用
store.subscribeAction
subscribeAction(handler: Function): Function<br>订阅 store 的 action。handler 会在每个 action 分发的时候调用并接收 action 描述和当前的 store 的 state 这两个参数:
https://vuex.vuejs.org/zh/api/#subscribeaction
示例
监听action的调用
plugins
plugins
一个数组,包含应用在 store 上的插件方法。这些插件直接接收 store 作为唯一参数,可以监听 mutation(用于外部地数据持久化、记录或调试)或者提交 mutation (用于内部数据,例如 websocket 或 某些观察者)
https://vuex.vuejs.org/zh/api/#plugins
图解vuex
子主题
newVue
渲染App
Route
在App中注册子组件
注入Store
可以使用$store把App和Store关联起来
dispatch commit
使用dispatch和commit触发store中state的修改
SSR
服务端渲染构建流程
服务端渲染构建流程
webpack dev server :使用热更替等其他功能,加快开发速度,但是无法添加服务端渲染的代码<br>node server: 执行服务端渲染的逻辑,使用vue的vue server rander 在node 环境中渲染出html代码,并返回给用户
KOA实现node server
掌握node基础知识后再看服务端渲染
高级组件开发
notification
实现基础组件
notification.vue
全局引入组件
import Notification from './components/notification'<br>
Vue.use(Notification)
全局注册组件和方法
Vue.component(Notification.name, Notification);
全局注册组件,在整个全局都可以使用这个component
Vue.prototype.$notify = notify;
把notify方法放到vue.prototype中,使得可以全局调用。
实现API
父类
import Notification from './notification.vue'<br>
notification.vue<br>notify传递的参数,会传到props里
func-notification.js
notify()实现
定义方法notify
方法notify,参数options
实例
NotificationConstructor<br>是组件父类Component的组件构造器
变量是notify中的options解构来的
行为
挂载显示
计算各个实例的偏移
弹窗消失
在父类中,<br>挂载时,设置定时器<br>销毁时,清除定时器<br>
弹窗消失后删除dom节点<br>减小内存消耗
绑定id
const id = `notification_${seed++}`<br> instance.id = id
删除
根据id删除dom,并调整offset
删除某个节点后,调整该节点上方节点的位置
调用
API的形式调用组件,传递参数
具体实现看/Users/sunhonghong/Downloads/coding-196/client/components/notification
Tab组件实现
组件结构设计
Tab组件结构
渲染后的结构
组件各部分设计
Tabs
Tab
TabContainer
行为
确定哪个Tab被选中
$parent
Tab的index和Tabs中的value相等时,该Tab被选中
数据传递的方式
祖先组件 ,传递数据 provide() <br>子孙组件,获取数据inject
不是响应式的<br>使用Object.defineProperty解决
$parent
不适合Tabs和Tab跨层级时
点击切换标签
子组件给父组件传递数据
子组件Tab
当Tab被点击时<br>Tab传递它的index给父组件Tabs的onChange方法
父组件接受子组件传来的数据
父组件Tabs
Tab接收Tab传来的数据,并将该数据发射给自定义事件change
在调用Tabs组件处,监听自定义事件change,并修改value值
调用
自定义事件change监听到Tabs传来的数据
修改value
修改tabValue,Tabs中的value随之改变,Tab就切换了
处理标签内容
将所有标签的内容全部展示出来
子组件
父组件
pane.$slot.default<br>在父组件中渲染子组件的slot
筛选对应的内容
只展示选中标签对应的内容
注意
slot不是reactive的
输入input,输入的内容展示会慢一拍,<br>这是因为Tabs认为props和data并没有改变,所以不会重新渲染<br>将pane相关的内容都抽离到Tab-container里
tabs
tab-container
具体实现,看/Users/sunhonghong/Downloads/coding-196/client/components/tabs
项目开发
0 条评论
下一页