当前位置: 首页 > Web前端 > JavaScript

【源码查看05】-View.extend

时间:2023-03-26 23:17:47 JavaScript

.base-toast{padding:10px;background:rgba(0,0,0,0.5);position:absolute;left:50%;top:10px;transform:translate(-50%,0);display:inline-block;margin:0auto;text-align:center;}.fadein{animation:animation_fade_in0.5s;}.fadeout{动画:animation_fade_out0.5s;}@keyframesanimation_fade_in{从{不透明度:0;}到{不透明度:1;}}@keyframesanimation_fade_out{从{不透明度:1;}到{不透明度:0;}}.toast-success{background:green;}.toast-error{background:red;}导航[[深度01]执行上下文](https://juejin.im/post/684490...)[[深度02]原型链](https://juejin.im/post/684490...)[[深入03]继承](https://juejin.im/post/684490...)[[深入04]事件循环](https://juejin.im/post/684490...)[[深入05]Curried偏函数函数记忆](https://juejin.im/post/684490...)[[深入06]隐式转换与运算符](https://juejin.im/post/684490...)[[深入07]浏览器缓存机制(http缓存机制)](https://juejin.im/post/684490...)[[深入08]前端安全](https://juejin.im/post/684490...)[[Deep09]DebounceThrottle](https://juejin.im/post/684490...)[[Deep10]DebounceThrottle](https://juejin.im/post/684490...)【【深入11】前端路由】(https://juejin.im/post/684490...)【【深入12】前端模块化】(https://juejin.im/post/684490...)【【深入13】观察者模式发布订阅模式双向数据绑定】(https://juejin.im/post/684490...)[[In-depth14]canvas](https://juejin.im/post/684490...)[[深入15]webSocket](https://juejin.im/post/684490...)[[In-深度16]webpack](https://juejin.im/post/684490...)[[深度17]http和https](https://juejin.im/post/684490...)[[深入18]CSS-interview](https://juejin.im/post/684490...)【【深入19】手写承诺】(https://juejin.im/post/684490...)【【深入20】手写函数】(https://juejin.im/post/684490...)[[react]Hooks](https://juejin.im/post/684490...)[[部署01]Nginx](https://juejin.im/post/684490...)[[部署02]Docker部署vue项目](https://juejin.im/post/684490...)[[部署03]gitlab-CI](https:///juejin.im/post/684490...)[[source-webpack01-pre-knowledge]AST抽象语法树](https://juejin.im/post/684490...)[[source-webpack02-pre-知识]Tapable](https://juejin.im/post/684490...)[[源码-webpack03]手写webpack-compiler简单编译过程](https://juejin.im/post/684490...)[[源码]ReduxReact-Redux01](https://juejin.im/post/684490...)[[源码]axios](https://juejin.im/post/684490...)[[源码]vuex](https://juejin.im/post/684490...)[[源码-vue01]数据响应和初始化渲染](https://juejin.im/post/684490...)[[小号sourcecode-vue02]]computedresponsive-初始化、访问、更新过程](https://juejin.im/post/684490...)[[source-vue03]watchlistenerattribute-初始化和更新](https:///觉进。im/post/684490...)[[source-vue04]Vue.set和vm.$set](https://juejin.im/post/684490...)[[source-vue05]Vue.extend](https://juejin.im/post/684490...)[[source-vue06]vue.nextTick和vm.$nextTick](https://juejin.im/post/684790...)预知一些词built-intag:built-intagreserved:reserved(tag被保留所以不能被注册为组件如果是保留标签,则组件名称不能使用)specification:specification(html5specificationHTML5specification)further:further(allowfurtherextension/mixin/pluginusageallowsfurtherextension...)(1)组件注册全局注册和局部注册(一)全局注册Vue.component(id,[definition])参数id:字符串类型,可以是MyComponent或my-componentdefinition:optional,functionorobjectdatamustbeafunction不包含el角色注册或访问全局组件全局注册组件可注:(data)中定义对象必须是(function),这样每个组件实例都可以维护一个独立的返回对象副本。id可以是一个字符串,有两种写法:MyComponent或my-component。全局注册的组件可以被所有子组件使用(2)本地注册在newVue()中通过参数对象中的components属性对象进行部分注册案例123//注册一个组件,传入一个扩展构造函数Vue.component('my-component',Vue.extend({/.../}))//注册组件,传入一个options对象(自动调用Vue.extend)Vue.component('my-component',{/.../})//获取注册的组件(总是返回构造函数)varMyComponent=Vue.component('my-component')Base/BaseButton.ts//全局注册component//1.这里是ts文件//2.如果是.vue文件,可以使用webpack的require.contextVue.component('BaseButton',{data(){return{message:'Thisisabasiccomponent-button'}},template:`

BaseButton
{{message}}
`,})//注意:在vue-cli3中,需要在vue.config.js中配置(runtimeCompiler:true)表示启用运行时+编译器版本//vue.config.jsmodule.exports={runtimeCompiler:true,//运行时+编译器版本}Base/BaseButton.ts------------------简单的Vue.component全局注册BaseButton组件/BaseButton.vue------------------使用require.context实现Basefile自动全局注册文件夹/index.ts中的所有组件----------------------Automatedglobalregistrationlogicindex.ts如下importVuefrom'vue'constrequireContext=require.context('.',false,/.vue$/)requireContext.keys().forEach(fileName=>{constcomponentModule=requireContext(fileName)const组件=cOmponentModule.defaultVue.component(component.name,component)})require.contextinVue官网案例:https://cn.vuejs.org/v2/guide/components-registration.html(2)Vue.extend(options)-api参数options:包含组件选项的对象注意:options.data必须是一个函数。Vue.component()和Vue.extend()的参数对象中的数据必须是一个函数。Usage使用基本的Vue构建Toast,创建一个子类案例(封装了一个全局的基础toast组件)toast是一个基础组件,会在多个地方使用,所以不要在里面导入每个用到的组件都注册在components中,但是挂在vue.prototype上的toast上并没有放在vue项目的DOM根节点,因为会受到路由的影响,而是一个独立的节点Base全局基础组件目录结构src/components/base/index.js/toast.vuesrc/components/base/toast.vue正常写一个显示的toast组件toast组件中的数据可以通过Vue.extend生成的子类实例的参数对象中的数据进行修改[src/components/base/toast.vue].base-toast{padding:10px;background:rgba(0,0,0,0.5);position:absolute;left:50%;top:10px;transform:translate(-50%,0);display:inline-block;margin:0auto;text-align:center;}.fadein{animation:animation_fade_in0.5s;}.fadeout{动画:animation_fade_out0.5s;}@keyframesanimation_fade_in{从{不透明度:0;}到{不透明度:1;}}@keyframesanimation_fade_out{从{不透明度:1;}到{不透明度:0;}}.toast-success{background:green;}.toast-error{background:red;}src/components/base/index.js---第二步:[src/components/base/index.js]importVuefrom"vue”;从“./toast.vue”导入Toast;constgeneratorToast=({message,type,duration=200})=>{constToastConstructor=Vue.extend(Toast);//------------------Vue.extend()生成Vue子类consttoastInstance=newToastConstructor({//----------------新建子类,生成组件实例el:document.createElement("div"),//------------------------组件挂在节点data(){//----------------------------------------------------与Toast组件中的数据合并return{message,类型,显示:真,淡入淡出:真,};},});setTimeout(()=>{toastInstance.fade=false;//----------------------------动画,提前时间},duration-500);setTimeout(()=>{toastInstance.show=false;//------------------------------显示隐藏},持续时间);document.body.appendChild(toastInstance.$el);//-----------------组件挂在位置};exportdefault{//--------------------------------------------插件对象的安装方法install(){Vue.prototype.$BaseToast=generatorToast;},};//Vue.use(option)//option可以是一个函数,也可以是一个带有install方法的对象//这里toast/index被封装成一个vue插件,通过Vue.use()注册,即,执行install方法src/main.js入口文件第三步:importsrc/components/base/index.jsVue.use()registerpluginimportVuefrom'vue'importAppfrom'./App.vue'importToastfrom'./components/base'Vue.config.productionTip=falseVue.use(Toast)//--------------------------------------------vue插件注册newVue({render:h=>h(App),}).$mount('#app')src/App.vue第4步:[src/App.vue]使用Vue.extend()一句话总结源码:使用基本的Vue构造函数创建子类字体>Vue.extend=function(extendOptions){extendOptions=extendOptions||{};//如果没有传递参数,则分配一个空对象varSuper=this;//这是指VuevarSuperId=Super.cid;//SuperId=>idvarcachedCtors=extendOptions._Ctor||(extendOptions._Ctor={});//缓存Ctors//用于缓存Constructor//如果参数对象中不存在_Ctor属性,则将extendOptions._Ctor={}赋值给一个空对象if(cachedCtors[SuperId]){//如果有缓存,则直接返回返回cachedCtors[SuperId]}varname=extendOptions.name||super.options.name;//name//参数对象中没有name属性,即使用父类options的name属性if(name){validateComponentName(name);//validateComponentName()验证名字的合法性//1.不能是slot组件这样的内置标签名//2.不能是HTML5的保留关键字标签}varSub=functionVueComponent(options){//定义一个子类this._init(options);};Sub.prototype=Object.create(Super.prototype);//将(子类原型的原型)指向(父类原型)//使得(子类的实例)可以继承(父类原型上的属性和方法)Sub.prototype.constructor=Sub;//将原型上的constructor属性指向自己,防止prototype.constructor指向SubSub.cid=cid++;Sub.options=mergeOptionsafterprototypemodified(Super.options,extendOptions);//Mergeoptions=>合并父类的选项和参数对象Sub['super']=Super;//将super属性挂载到子类,指向父类//对于props和计算属性,我们在扩展时间定义了代理getters//Vue实例e,在扩展原型上。这//避免为每个创建的实例调用Object.defineProperty。if(Sub.options.props){initProps$1(Sub);//props属性存在,使props成为一层代理//initProps方法允许用户访问this[propName]相当于访问this._props[propName]}if(Sub.options.computed){initComputed$1(Sub);//同上}//允许进一步扩展/混合/插件使用//继承相关属性Sub.extend=Super.extend;Sub.mixin=Super.mixin;Sub.use=Super.use;//创建资产寄存器,所以扩展类//也可以拥有它们的私有资产。ASSET_TYPES.forEach(function(type){Sub[type]=Super[type];});//继承组件指令过滤器//varASSET_TYPES=[//'component',//'directive',//'filter'//];//启用递归自查找if(name){Sub.options.components[name]=Sub;//将Sub保存到组件属性}Sub.superOptions=Super.options;Sub.extendOptions=extendOptions;Sub.sealedOptions=extend({},Sub.options);//缓存构造函数cachedCtors[SuperId]=Sub;//有SubreturnSub//返回子};数据Vue.extend源码https://juejin.im/post/684490...Vue.extend源码https://zhuanlan.zhihu.com/p/...toast组件1https://juejin.im/post/684490...Vue.extend源码https://zhuanlan.zhihu.com/p/...toast组件1juejin.im/post/684490...toast组件2https://juejin.im/帖子/684490...