茂名整站优化,网站建设的优缺点,python 如何做网站,yangdesign工业设计公司Vue2高级用法 1、mixin复用【vue不会用了#xff0c;了解一下】1.1 基础使用1.2 选项合并1.3 全局混入1.4 细数 mixin 存在的问题 2、vue.js 动画特效#xff06; 常见组件库介绍2.1 进入/离开基础使用示例2.2 进入/离开自定义过度类名2.3 进入/离开动画钩子2.4 多组件过渡与… Vue2高级用法 1、mixin复用【vue不会用了了解一下】1.1 基础使用1.2 选项合并1.3 全局混入1.4 细数 mixin 存在的问题 2、vue.js 动画特效 常见组件库介绍2.1 进入/离开基础使用示例2.2 进入/离开自定义过度类名2.3 进入/离开动画钩子2.4 多组件过渡与列表过渡2.5 状态过渡2.6 常用动画相关库 3、 插槽3.1 插槽的三种使用方法 4、插件4.1 定义插件4.2 使用插件4.3 插件化机制原理4.4 具体实践 5、过滤器5.1 使用过滤器5.2 定义过滤器5.3 串联过滤器 1、mixin复用【vue不会用了了解一下】
mixin实现复用的同时带来了很多问题例如命名污染、依赖不透明 Vue3 用 Composition API替代
1.1 基础使用
混入 (mixin) 提供了一种非常灵活的方式来分发 Vue 组件中的可复用功能。 例子
// 定义一个混入对象
var myMixin {created: function () {this.hello()},methods: {hello: function () {console.log(hello from mixin!)}}
}// 定义一个使用混入对象的组件
var Component Vue.extend({mixins: [myMixin]
})var component new Component() // hello from mixin!1.2 选项合并
当组件和混入对象含有同名选项时这些选项将以恰当的方式进行“合并”。
值为对象的选项合并成一个对象同名的话组件的值会覆盖混入对象钩子函数合并成一个数组都执行混入对象的钩子先执行组件后执行组件的函数覆盖混入的
比如数据对象在内部会进行递归合并并在发生冲突时以组件数据优先。
var mixin {data: function () {return {message: hello,foo: abc}}
}new Vue({mixins: [mixin],data: function () {return {message: goodbye,bar: def}},created: function () {console.log(this.$data)// { message: goodbye, foo: abc, bar: def }}
})同名钩子函数将合并为一个数组因此都将被调用。另外混入对象的钩子将在组件自身钩子之前调用。
var mixin {created: function () {console.log(混入对象的钩子被调用)}
}new Vue({mixins: [mixin],created: function () {console.log(组件钩子被调用)}
})// 混入对象的钩子被调用
// 组件钩子被调用值为对象的选项例如 methods、components 和 directives将被合并为同一个对象。两个对象键名冲突时取组件对象的键值对。
var mixin {methods: {foo: function () {console.log(foo)},conflicting: function () {console.log(from mixin)}}
}var vm new Vue({mixins: [mixin],methods: {bar: function () {console.log(bar)},conflicting: function () {console.log(from self)}}
})vm.foo() // foo
vm.bar() // bar
vm.conflicting() // from self注意Vue.extend() 也使用同样的策略进行合并。
1.3 全局混入
混入也可以进行全局注册。使用时格外小心一旦使用全局混入它将影响每一个之后创建的 Vue 实例。使用恰当时这可以用来为自定义选项注入处理逻辑。
// 为自定义的选项 myOption 注入一个处理器。
Vue.mixin({created: function () {var myOption this.$options.myOptionif (myOption) {console.log(myOption)}}
})new Vue({myOption: hello!
})
// hello!1.4 细数 mixin 存在的问题
命名冲突vue组件的值会覆盖mixin选项相同类型的生命周期钩子添加到同一个数组里依次执行依赖不透明mixin 和使用它的组件之间没有层次关系。组件可以用mixin的数据mixin可以用设定在vue里的数据如上文的this.$options.myOption。这样要是修改mixin就比较复杂。
2、vue.js 动画特效 常见组件库介绍 Vue 在插入、更新或者移除 DOM 时提供多种不同方式的应用过渡效果。包括以下工具 在 CSS 过渡和动画中自动应用 class可以配合使用第三方 CSS 动画库如 Animate.css在过渡钩子函数中使用 JavaScript 直接操作 DOM可以配合使用第三方 JavaScript 动画库如 Velocity.js Vue 提供了 transition 的封装组件在下列情形中可以给任何元素和组件添加进入/离开过渡
条件渲染 (使用 v-if)条件展示 (使用 v-show)动态组件组件根节点
2.1 进入/离开基础使用示例
div iddemobutton v-on:clickshow !showToggle/buttontransition namefadep v-ifshowhello/p/transition
/div.fade-enter-active, .fade-leave-active {transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {opacity: 0;
}export default {data() {show: true}
}2.2 进入/离开自定义过度类名
link hrefhttps://cdn.jsdelivr.net/npm/animate.css3.5.1 relstylesheet typetext/cssdiv idexample-3button clickshow !showToggle render/buttontransitionnamecustom-classes-transitionenter-active-classanimated tadaleave-active-classanimated bounceOutRightp v-ifshowhello/p/transition
/div2.3 进入/离开动画钩子
transitionv-on:before-enterbeforeEnterv-on:enterenterv-on:after-enterafterEnterv-on:enter-cancelledenterCancelledv-on:before-leavebeforeLeavev-on:leaveleavev-on:after-leaveafterLeavev-on:leave-cancelledleaveCancelled
!-- ... --
/transition2.4 多组件过渡与列表过渡
div idlist-demo classdemobutton v-on:clickaddAdd/buttonbutton v-on:clickremoveRemove/buttontransition-group namelist tagpspan v-foritem in items v-bind:keyitem classlist-item{{ item }}/span/transition-group
/div{data: {items: [1,2,3,4,5,6,7,8,9],nextNum: 10},methods: {randomIndex: function () {return Math.floor(Math.random() * this.items.length)},add: function () {this.items.splice(this.randomIndex(), 0, this.nextNum)},remove: function () {this.items.splice(this.randomIndex(), 1)},}
}.list-item {display: inline-block;margin-right: 10px;
}
.list-enter-active, .list-leave-active {transition: all 1s;
}
.list-enter, .list-leave-to
/* .list-leave-active for below version 2.1.8 */ {opacity: 0;transform: translateY(30px);
}2.5 状态过渡
通过状态去驱动视图更新从而实现动画过渡
script srchttps://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.4/gsap.min.js/scriptdiv idanimated-number-demoinput v-model.numbernumber typenumber step20p{{ animatedNumber }}/p
/div{data: {number: 0,tweenedNumber: 0},computed: {animatedNumber: function() {return this.tweenedNumber.toFixed(0);}},watch: {number: function(newValue) {gsap.to(this.$data, { duration: 0.5, tweenedNumber: newValue });//gsap js动画库 gsap.to要变化的对象数据对象或者dom对象,{对象里变化的参数},}}
}2.6 常用动画相关库
gsapanimated.csstween.js
3、 插槽
插槽 slot 是写在子组件的代码中供父组件使用的占位符
3.1 插槽的三种使用方法
默认插槽没有名字普通的具名插槽带名字父组件可以根据名字插入子组件的对应的位置多个区分占位符位置slot name‘header’区分位置作用域插槽父组件可以使用子组件插槽传过来的games数据传值
ps vue 2.6.0版本之后的slot插槽 用v-slot:default‘ctx’ 替代slot‘’。
默认和具名案例
templatediv classparent我是父组件Child/Child/div
/templatescript
import Child from ./components/Child.vueexport default {name: app,components: {Child}
}
/scriptstyle
.parent {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;padding:10px;background-color:#eee;
}
/styletemplatediv classhello我是子组件!-- 如果父组件没有填充内容就显示slot里的默认内容如果父组件填充内容显示父组件的内容 --div!-- 具名插槽 --slot nameheader把头放这里/slot /divdiv!-- 默认插槽 --slot这里是默认插槽/slot /divdiv!-- 具名插槽 --slot namefooter把尾巴放这里/slot/div/div
/templatescript
export default {name: Child,}
/script!-- Add scoped attribute to limit CSS to this component only --
style scoped.hello{background-color: #097493;color: #fff;padding:20px;
}
.hellodiv{padding:10px;border: 1px solid red;margin: 5px;
}
/style当父组件什么都没传时子组件按自己默认的显示 当父组件填入对应内容将会替换子组件的默认占位子组件也可以不设置默认内容 父组件改为
templatediv classparent我是父组件Childdiv slotheader 替换头部内容/divdiv slotheader替换头部内容2/divdiv slotfooter替换底部内容/divdiv没有定义slot,默认放默认插槽/divdiv如果再来一个默认插槽呢都会进入默认插槽里/div/Child/div
/templatescript
import Child from ./components/Child.vueexport default {name: app,components: {Child}
}
/scriptstyle
.parent {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;padding:10px;background-color:#eee;
}
/style显示 作用域插槽子组件定义数据传出去在父组件用slot-scope接收并使用就是作用域插槽的功能
templatediv classparent我是父组件Childdiv slotheader 替换头部内容/divdiv slotfooter slot-scopeuser替换底部内容{{user.games}}/divdiv slot-scope{games}没有定义slot,默认放默认插槽{{games}}/div/Child/div
/templatescript
import Child from ./components/Child.vueexport default {name: app,components: {Child}
}
/scriptstyle
.parent {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: center;color: #2c3e50;margin-top: 60px;padding:10px;background-color:#eee;
}
/styletemplatediv classhello我是子组件!-- 如果父组件没有填充内容就显示slot里的默认内容如果父组件填充内容显示父组件的内容 --div!-- 具名插槽 --slot :gamesgames nameheader把头放这里/slot /divdiv!-- 默认插槽 --slot :gamesgames这里是默认插槽/slot /divdiv!-- 具名插槽 --slot :gamesgames namefooter把尾巴放这里/slot/div/div
/templatescript
export default {name: Child,data() {return {games:[王者荣耀,吃鸡,斗地主]}},
}
/script!-- Add scoped attribute to limit CSS to this component only --
style scoped.hello{background-color: #097493;color: #fff;padding:20px;
}
.hellodiv{padding:10px;border: 1px solid red;margin: 5px;
}
/style显示
4、插件
插件可以是对象或者是一个函数。如果是对象那么对象中需要提供 install 函数如果是函数形态需要跟前面提到的 install 函数保持一致。 install 是组件安装的一个方法跟 npm install 完全不一样npm install 是一个命令
4.1 定义插件
const MyPlugin {install(Vue, options) {// 1. 添加全局方法或 propertyVue.myGlobalMethod function () {// 逻辑...}// 2. 添加全局资源Vue.directive(my-directive, {bind (el, binding, vnode, oldVnode) {// 逻辑...}...})// 3. 注入组件选项Vue.mixin({created: function () {// 逻辑...}...})// 4. 添加实例方法Vue.prototype.$myMethod function (methodOptions) {// 逻辑...}}
};4.2 使用插件
Vue.use(MyPlugin);{{ $myMethod }}4.3 插件化机制原理
export function initUse (Vue: GlobalAPI) {Vue.use function (plugin: Function | Object) {// 获取已经安装的插件const installedPlugins (this._installedPlugins || (this._installedPlugins []))// 看看插件是否已经安装如果安装了直接返回if (installedPlugins.indexOf(plugin) -1) {return this}// toArray(arguments, 1)实现的功能就是获取Vue.use(plugin,xx,xx)中的其他参数。// 比如 Vue.use(plugin,{size:mini, theme:black})就会回去到plugin意外的参数const args toArray(arguments, 1)// 在参数中第一位插入Vue从而保证第一个参数是Vue实例args.unshift(this)// 插件要么是一个函数要么是一个对象(对象包含install方法)if (typeof plugin.install function) {// 调用插件的install方法并传入Vue实例plugin.install.apply(plugin, args)} else if (typeof plugin function) {plugin.apply(null, args)}// 在已经安装的插件数组中放进去installedPlugins.push(plugin)return this}
}4.4 具体实践
Vue-Router for Vue2
import View from ./components/view
import Link from ./components/linkexport let _Vueexport function install (Vue) {if (install.installed _Vue Vue) returninstall.installed true_Vue Vueconst isDef v v ! undefinedconst registerInstance (vm, callVal) {let i vm.$options._parentVnodeif (isDef(i) isDef(i i.data) isDef(i i.registerRouteInstance)) {i(vm, callVal)}}Vue.mixin({beforeCreate () {if (isDef(this.$options.router)) {this._routerRoot thisthis._router this.$options.routerthis._router.init(this)Vue.util.defineReactive(this, _route, this._router.history.current)} else {this._routerRoot (this.$parent this.$parent._routerRoot) || this}registerInstance(this, this)},destroyed () {registerInstance(this)}})Object.defineProperty(Vue.prototype, $router, {get () { return this._routerRoot._router }})Object.defineProperty(Vue.prototype, $route, {get () { return this._routerRoot._route }})Vue.component(RouterView, View)Vue.component(RouterLink, Link)const strats Vue.config.optionMergeStrategies// use the same hook merging strategy for route hooksstrats.beforeRouteEnter strats.beforeRouteLeave strats.beforeRouteUpdate strats.created
}for Vue3 install(app: App) {const router thisapp.component(RouterLink, RouterLink)app.component(RouterView, RouterView)app.config.globalProperties.$router routerObject.defineProperty(app.config.globalProperties, $route, {enumerable: true,get: () unref(currentRoute),})// this initial navigation is only necessary on client, on server it doesnt// make sense because it will create an extra unnecessary navigation and could// lead to problemsif (isBrowser // used for the initial navigation client side to avoid pushing// multiple times when the router is used in multiple apps!started currentRoute.value START_LOCATION_NORMALIZED) {// see abovestarted truepush(routerHistory.location).catch(err {if (__DEV__) warn(Unexpected error when starting the router:, err)})}const reactiveRoute {} as {[k in keyof RouteLocationNormalizedLoaded]: ComputedRefRouteLocationNormalizedLoaded[k]}for (const key in START_LOCATION_NORMALIZED) {// ts-expect-error: the key matchesreactiveRoute[key] computed(() currentRoute.value[key])}app.provide(routerKey, router)app.provide(routeLocationKey, reactive(reactiveRoute))app.provide(routerViewLocationKey, currentRoute)const unmountApp app.unmountinstalledApps.add(app)app.unmount function () {installedApps.delete(app)// the router is not attached to an app anymoreif (installedApps.size 1) {// invalidate the current navigationpendingLocation START_LOCATION_NORMALIZEDremoveHistoryListener removeHistoryListener()removeHistoryListener nullcurrentRoute.value START_LOCATION_NORMALIZEDstarted falseready false}unmountApp()}// TODO: this probably needs to be updated so it can be used by vue-termuiif ((__DEV__ || __FEATURE_PROD_DEVTOOLS__) isBrowser) {addDevtools(app, router, matcher)}},}5、过滤器
Vue.js允许我们自定义过滤器对数据进行格式化。过滤器应该放在JS表达式的尾部由管道符号连接。过滤器可以用在两个地方双花括号差值和v-bind表达式。
5.1 使用过滤器
!-- 在双花括号中 --
{{ message | capitalize }}!-- 在 v-bind 中 --
div v-bind:idmessage | capitalize/div5.2 定义过滤器
组件中定义过滤器
filters: {capitalize: function (value) {if (!value) return value value.toString()return value.charAt(0).toUpperCase() value.slice(1)}
}全局中定义过滤器
Vue.filter(capitalize, function (value) {if (!value) return value value.toString()return value.charAt(0).toUpperCase() value.slice(1)
})new Vue({// ...
})5.3 串联过滤器
我们可以同时使用多个过滤器过滤器函数总接收表达式的值 (上一个过滤器的结果) 作为第一个参数。
{{ message | filterA | filterB }}过滤器是 JavaScript 函数因此可以接收参数 ps没有传参时候默认传入当前值filterA等价于filterA(message)
{{ message | filterA(arg1, arg2) }}