组件可以扩展 HTML 元素,封装可重用的代码
在较高层面上,组件是自定义元素, Vue.js 的编译器为它添加特殊功能
在有些情况下,组件也可以是原生 HTML 元素的形式,以 is 特性扩展。
<div id="example"> <my-component>my-component> div>
// 注册全局组件,指定之前设定的元素名,然后传入对象 Vue.component('my-component', { template: 'A custom component!' }) // 创建根实例 new Vue({ el: '#example' })
不必在全局注册每个组件。通过使用组件实例选项注册,可以使组件仅在另一个实例/组件的作用域中可用
//将传入给组件的对象单独写 var Child = { template: 'A custom component!' } new Vue({ //通过components语法创建局部组件 //将组件仅仅放在这个vue实例里面使用 components: { // 将只在父模板可用 'my-component': Child } })
当使用 DOM 作为模版时(例如,将 el 选项挂载到一个已存在的元素上), 你会受到 HTML 的一些限制,
因为 Vue 只有在浏览器解析和标准化 HTML 后才能获取模版内容。尤其像这些元素 , , , 限制了能被它包裹的元素, 只能出现在其它元素内部。 <table> <my-row>...my-row> table> <table> <tr is="my-row">tr> table> data必须是函数 使用组件时,大多数可以传入到 Vue 构造器中的选项可以在注册组件时使用,有一个例外: data 必须是函数。 实际上 //这样会报错,提示data必须是一个函数 Vue.component('my-component', { template: '{{ message }}', data: { message: 'hello' } }) <div id="example-2"> <simple-counter>simple-counter> <simple-counter>simple-counter> <simple-counter>simple-counter> div> var data = { counter: 0 } Vue.component('simple-counter', { template: '{{ counter }}', // data 是一个函数,因此 Vue 不会警告, // 但是我们为每一个组件返回了同一个对象引用,所以改变其中一个会把其他都改变了 data: function () { return data } }) new Vue({ el: '#example-2' }) 避免出现同时改变数据的情况 //返回一个新的对象,而不是返回同一个data对象引用 data: function () { return { //字面量写法会创建新对象 counter: 0 } } 构成组件 组件意味着协同工作,通常父子组件会是这样的关系: 组件 A 在它的模版中使用了组件 B 。它们之间必然需要相互通信 父组件要给子组件传递数据,子组件需要将它内部发生的事情告知给父组件 然而,在一个良好定义的接口中尽可能将父子组件解耦是很重要的。这保证了每个组件可以在相对隔离的环境中书写和理解,也大幅提高了组件的可维护性和可重用性。 在 Vue.js 中,父子组件的关系可以总结为 props down, events up 。 父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。看看它们是怎么工作的。 prop 使用prop传递数据 组件实例的作用域是孤立的。这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。 使用 props 把数据传给子组件。 prop 是父组件用来传递数据的一个自定义属性 子组件需要显式地用 props 选项声明 “prop” <div id="example-2"> <child message="hello!">child> div> Vue.component('child', { // 声明 props,用数组形式的对象 props: ['message'], // 就像 data 一样,prop 可以用在模板内 // 同样也可以在 vm 实例中像 “this.message” 这样使用 template: '{{ message }}' }); new Vue({ el: '#example-2' }) 动态prop 用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件 <div id="example-2"> <input v-model="parentMsg"> <br> <child v-bind:my-message="parentMsg">child> div> Vue.component('child', { // 声明 props props: ['my-message'], template: '{{ myMessage }}' //如果写my-message会报错,需要转换为驼峰写法 }); new Vue({ el: '#example-2', data: { parentMsg: '' } }) 短横线和驼峰写法 HTML 特性不区分大小写。当使用非字符串模版时,prop的名字形式会从 camelCase 转为 kebab-case(短横线隔开) 在JavaScript里面使用驼峰写法,但是在html里面需要转成短横线写法 反之亦然,vue会自动处理来自html的短横线写法转为驼峰写法 字面量语法和动态语法 <comp some-prop="1">comp> <comp v-bind:some-prop="1">comp> 单向数据流 prop 是单向绑定的 当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解。 每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你不应该在子组件内部改变 prop 。如果你这么做了,Vue 会在控制台给出警告。 通常有两种改变 prop 的情况: prop 作为初始值传入,子组件之后只是将它的初始值作为本地数据的初始值使用 定义一个局部 data 属性,并将 prop 的初始值作为局部数据的初始值。 <div id="example-2"> <child initial-counter="10">child> div> Vue.component('child', { props: ['initialCounter'],//这里用驼峰写法 data: function () { //转为一个局部变量,写一个data对象给组件使用 return {counter: this.initialCounter} }, template: '{{ counter }}' }); new Vue({ el: '#example-2' }) prop 作为需要被转变的原始值传入。 定义一个 computed 属性,此属性从 prop 的值计算得出。 //例子没有写完,但是根据第一个例子可以知道利用computed的手法原理其实跟写一个data差不多 props: ['size'], computed: { normalizedSize: function () { return this.size.trim().toLowerCase() } } 注意在 JavaScript 中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它会影响父组件的状态。 prop验证 组件可以为 props 指定验证要求,当组件给其他人使用时这很有用。 Vue.component('example', { props: { // 基础类型检测 (`null` 意思是任何类型都可以) propA: Number, // 多种类型 propB: [String, Number], // 必传且是字符串 propC: { type: String, required: true }, // 数字,有默认值 propD: { type: Number, default: 100 }, // 数组/对象的默认值应当由一个工厂函数返回 propE: { type: Object, default: function () { return { message: 'hello' } } }, // 自定义验证函数 propF: { validator: function (value) { return value > 10 } } } }) 自定义事件 每个 Vue 实例都实现了事件接口(Events interface) 使用 $on(eventName) 监听事件 使用 $emit(eventName) 触发事件 父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。 <div id="counter-event-example"> <p>{{ total }}p> <button-counter v-on:increment1="incrementTotal">button-counter> <button-counter v-on:increment1="incrementTotal">button-counter> div> Vue.component('button-counter', { //监听click事件,处理程序为increment(子组件定义的方法) template: '{{ counter }}', //每一个counter都是独立的对象属性 data: function () { return { counter: 0 } }, //子组件的方法 methods: { increment: function () { this.counter += 1; //在子组件里面直接触发之前监听的increment1事件来执行父组件的方法 this.$emit('increment1'); } }, }) new Vue({ el: '#counter-event-example', data: { total: 0 }, //父组件的方法 methods: { incrementTotal: function () { this.total += 1 } } }) 1.组件之间因为作用域不同的关系,所以相互独立,所以子组件想要使用父组件的方法的话需要做一个新的监听映射 给组件绑定原生事件 <my-component v-on:click.native="doTheThing">my-component> 使用自定义事件的表单输入组件 自定义事件也可以用来创建自定义的表单输入组件,使用 v-model 来进行数据双向绑定。所以要让组件的 v-model 生效,它必须: 接受一个 value 属性 在有新的 value 时触发 input 事件 <input v-model="something"> <input v-bind:value="something" v-on:input="something = $event.target.value"> 一个非常简单的货币输入: <currency-input v-model="price">currency-input> Vue.component('currency-input', { template: '\ \ $\ \ \ ', props: ['value'], //父组件将绑定的value传给子组件 methods: { // 不是直接更新值,而是使用此方法来对输入值进行格式化和位数限制 updateValue: function (value) { var formattedValue = value //对值进行处理 // 删除两侧的空格符 .trim() // 保留 2 小数位和2位数 .slice(0, value.indexOf('.') + 3) // 如果值不统一,手动覆盖以保持一致,为了保持输入框显示内容跟格式化内容一致 if (formattedValue !== value) { //因为注册是一个input元素,所以this.$refs 就是input元素 this.$refs.input.value = formattedValue } //手动触发input事件,将格式化后的值传过去,这是最终显示输入框的输出 this.$emit('input', Number(formattedValue)) } } }) //实例化vue实例的 new Vue({ el: '#aa', //要绑定一个vue实例,例如包裹一个id为aa的div data:{ price:'' //v-model要有数据源 } }) ref 被用来给元素或子组件注册引用信息。引用信息会根据父组件的 $refs 对象进行注册。如果在普通的DOM元素上使用,引用信息就是元素; 如果用在子组件上,引用信息就是组件实例 ref 这是一个比较完整的例子: <div id="app"> <currency-input label="Price" v-model="price" >currency-input> <currency-input label="Shipping" v-model="shipping" >currency-input> <currency-input label="Handling" v-model="handling" >currency-input> <currency-input label="Discount" v-model="discount" >currency-input> <p>Total: ${{ total }}p> div> Vue.component('currency-input', { template: '\ \ {{ label }}\ $\ \ \ ', props: { //多个prop传递,因为prop是对象,只要是对象格式就行 value: { type: Number, default: 0 }, label: { type: String, default: '' } }, mounted: function () { //这是vue的过渡状态,暂时忽略不影响理解 this.formatValue() }, methods: { updateValue: function (value) { var result = currencyValidator.parse(value, this.value) if (result.warning) { // 这里也使用了$refs获取引用注册信息 this.$refs.input.value = result.value } this.$emit('input', result.value) }, formatValue: function () { this.$refs.input.value = currencyValidator.format(this.value) //这里注意下,这个this是prop传递过来的,也相当于这个组件作用域 }, selectAll: function (event) { //event可以获取原生的js事件 // Workaround for Safari bug // http://stackoverflow.com/questions/1269722/selecting-text-on-focus-using-jquery-not-working-in-safari-and-chrome setTimeout(function () { event.target.select() }, 0) } } }) new Vue({ el: '#app', data: { price: 0, shipping: 0, handling: 0, discount: 0 }, computed: { total: function () { return (( this.price * 100 + this.shipping * 100 + this.handling * 100 - this.discount * 100 ) / 100).toFixed(2) } } }) 非父子组件通信 在简单的场景下,使用一个空的 Vue 实例作为中央事件总线: var bus = new Vue() // 触发组件 A 中的事件 bus.$emit('id-selected', 1) /* 通过on来监听子组件的事件来实现传递 */ // 在组件 B 创建的钩子中监听事件 bus.$on('id-selected', function (id) { // ... }) 使用Slot分发内容 为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板。这个过程被称为 内容分发 (或 “transclusion” 如果你熟悉 Angular) 编译作用域 组件作用域简单地说是:父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。假定 someChildProperty 是子组件的属性,上例不会如预期那样工作。父组件模板不应该知道子组件的状态。 <child-component v-show="someChildProperty">child-component> 如果要绑定子组件内的指令到一个组件的根节点,应当在它的模板内这么做: Vue.component('child-component', { // 有效,因为是在正确的作用域内 template: 'Child', data: function () { return { //因为这个属性在当前组件内编译(创建了) someChildProperty: true } } }) 类似地,分发内容是在父组件作用域内编译。 单个Slot 除非子组件模板包含至少一个 插口,否则父组件的内容将会被丢弃。 当子组件模板只有一个没有属性的 slot 时,父组件整个内容片段将插入到 slot 所在的 DOM 位置,并替换掉 slot 标签本身。 备用内容在子组件的作用域内编译,并且只有在宿主元素为空,且没有要插入的内容时才显示备用内容。 <div id="aa"> <h1>我是父组件的标题h1> <my-component>my-component> <my-component> <p>这是一些初始内容p> <p>这是更多的初始内容p> my-component> div> Vue.component('my-component', { //my-component 组件有下面模板 template: '\ \ 我是子组件的标题 \ \ //有slot插口,所以没有被父组件丢弃 只有在没有要分发的内容时才会显示。\ \ \ ' }) new Vue({ el: '#aa', }) 渲染结果: <div id="aa"><h1>我是父组件的标题h1> <div> <h2>我是子组件的标题h2> 只有在没有要分发的内容时才会显示。 div> <div> <h2>我是子组件的标题h2> <p>这是一些初始内容p> <p>这是更多的初始内容p> div> div> 有名字的Slot 元素可以用一个特殊的属性 name 来配置如何分发内容。多个 slot 可以有不同的名字。具名 slot 将匹配内容片段中有对应 slot 特性的元素。 仍然可以有一个匿名 slot ,它是默认 slot ,作为找不到匹配的内容片段的备用插槽。如果没有默认的 slot ,这些找不到匹配的内容片段将被抛弃。 <div id="aa"> <app-layout> <h1 slot="header">这里可能是一个页面标题h1> <p>主要内容的一个段落。p> <p>另一个主要段落。p> <p slot="footer">这里有一些联系信息p> app-layout> div> Vue.component('app-layout', { template: '\ \ \ //找到名字叫header的slot之后替换内容,这里替换的是整个DOM \ \ \ //因为slot没有属性,会将内容插入到slot的所在的DOM位置 \ \ \ \ ' }); new Vue({ el: '#aa', }) 渲染结果为: <div class="container"> <header> <h1>这里可能是一个页面标题h1> header> <main> <p>主要内容的一个段落。p> <p>另一个主要段落。p> main> <footer> <p>这里有一些联系信息p> footer> div> 作用域插槽(vue2.1) 作用域插槽是一种特殊类型的插槽,用作使用一个(能够传递数据到)可重用模板替换已渲染元素。 在子组件中,只需将数据传递到插槽,就像你将 prop 传递给组件一样 在父级中,具有特殊属性 scope 的 元素,表示它是作用域插槽的模板。scope 的值对应一个临时变量名,此变量接收从子组件中传递的 prop 对象 <div id="parent" class="parent"> <child> <template scope="props"> <span>hello from parentspan> <span>{{ props.text }}span> template> child> div> Vue.component('child', { props: ['props'], //这个写不写都可以,作用域插槽固定会接收prop对象,而且这个prop对象是肯定存在的 template: '\ \ \ //在子组件里直接将数据传递给slot \ ' }); new Vue({ el: '#parent', }) 渲染结果: <div class="parent"> <div class="child"> <span>hello from parentspan> <span>hello from childspan> div> div> 另外一个例子,作用域插槽更具代表性的用例是列表组件,允许组件自定义应该如何渲染列表每一项 <div id="parent"> <my-awesome-list :items="items"> <template slot="item" scope="props"> <li class="my-fancy-item">{{ props.text }}li> template> my-awesome-list> div> Vue.component('my-awesome-list', { props:['items'], //需要声明prop为items,需要是为下面的循环遍历的items的数据源做设定,位置3 template: '\ \ \ //在slot中,循环遍历输出items的text,位置4 \ \ ' }); new Vue({ el: '#parent', data : { items:[ //初始化items数据 {text:"aa"}, {text:"bb"} ] } }) 位置1,实现了一个组件的prop绑定,prop需要在组件里面声明,这里绑定的是items,这是要将父组件的items传递到子组件,所以在位置3里面需要声明,在vue实例要初始化 位置2,这里scope的props是代表作用域插槽接收来自prop对象的数据,props.text是代表每一个li要输出的是prop对象的text属性 位置3,在组件里声明props,为了接收父组件绑定的items属性,然后将其给位置4的循环使用 位置4,这里绑定了text属性,就是前呼位置2里面输出的prop对象的text属性 动态组件 多个组件可以使用同一个挂载点,然后动态地在它们之间切换。使用保留的 元素,动态地绑定到它的 is 特性 var vm = new Vue({ el: '#example', data: { currentView: 'home' //默认值 }, components: { //根据不同的值进行不同的组件切换,这里用components写法 home: { /* ... */ }, posts: { /* ... */ }, archive: { /* ... */ } } }) <component v-bind:is="currentView"> component> keep-alive 如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。为此可以添加一个 keep-alive 指令参数 <keep-alive> <component :is="currentView"> component> keep-alive> 杂项 编写可复用组件 在编写组件时,记住是否要复用组件有好处。一次性组件跟其它组件紧密耦合没关系,但是可复用组件应当定义一个清晰的公开接口。Vue 组件的 API 来自三部分 - props, events 和 slots : Props 允许外部环境传递数据给组件 Events 允许组件触发外部环境的副作用 Slots 允许外部环境将额外的内容组合在组件中。 <my-component :foo="baz" :bar="qux" @event-a="doThis" @event-b="doThat" > <img slot="icon" src="..."> <p slot="main-text">Hello!p> my-component> 子组件索引 尽管有 props 和 events ,但是有时仍然需要在 JavaScript 中直接访问子组件。为此可以使用 ref 为子组件指定一个索引 ID 。 <div id="parent"> <user-profile ref="profile">user-profile> div> var parent = new Vue({ el: '#parent' }) // 访问子组件 var child = parent.$refs.profile 当 ref 和 v-for 一起使用时, ref 是一个数组或对象,包含相应的子组件。 $refs 只在组件渲染完成后才填充,并且它是非响应式的。它仅仅作为一个直接访问子组件的应急方案——应当避免在模版或计算属性中使用 $refs 。 ref 被用来给元素或子组件注册引用信息。引用信息会根据父组件的 $refs 对象进行注册。如果在普通的DOM元素上使用,引用信息就是元素; 如果用在子组件上,引用信息就是组件实例 ref 组件命名约定 当注册组件(或者 props)时,可以使用 kebab-case ,camelCase ,或 TitleCase 。Vue 不关心这个。 在 HTML 模版中,请使用 kebab-case 形式: // 在组件定义中 components: { // 使用 kebab-case 形式注册--横线写法 'kebab-cased-component': { /* ... */ }, // register using camelCase --驼峰写法 'camelCasedComponent': { /* ... */ }, // register using TitleCase --标题写法 'TitleCasedComponent': { /* ... */ } } <kebab-cased-component>kebab-cased-component> <camel-cased-component>camel-cased-component> <title-cased-component>title-cased-component> 递归组件 组件在它的模板内可以递归地调用自己,不过,只有当它有 name 选项时才可以 当你利用Vue.component全局注册了一个组件, 全局的ID作为组件的 name 选项,被自动设置. //组件可以用name来写名字 name: 'unique-name-of-my-component' //也可以在创建的时候默认添加名字 Vue.component('unique-name-of-my-component', { // ... }) //如果同时使用的话,递归的时候就会不断递归自己,导致溢出 name: 'stack-overflow', template: '' 使用-v-once-的低级静态组件-Cheap-Static-Component 尽管在 Vue 中渲染 HTML 很快,不过当组件中包含大量静态内容时,可以考虑使用 v-once 将渲染结果缓存起来,就像这样: Vue.component('terms-of-service', { template: '\ \ Terms of Service\ ... a lot of static content ...\ \ ' }) v-once只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。 你可能感兴趣的:(vue,2.0,vue2.0-组件,vue2.0) element实现动态路由+面包屑 软件技术NINI vue案例vue.js前端 el-breadcrumb是ElementUI组件库中的一个面包屑导航组件,它用于显示当前页面的路径,帮助用户快速理解和导航到应用的各个部分。在Vue.js项目中,如果你已经安装了ElementUI,就可以很方便地使用el-breadcrumb组件。以下是一个基本的使用示例:安装ElementUI(如果你还没有安装的话):你可以通过npm或yarn来安装ElementUI。bash复制代码npmi 利用LangChain的StackExchange组件实现智能问答系统 nseejrukjhad langchainmicrosoft数据库python 利用LangChain的StackExchange组件实现智能问答系统引言在当今的软件开发世界中,StackOverflow已经成为程序员解决问题的首选平台之一。而LangChain作为一个强大的AI应用开发框架,提供了StackExchange组件,使我们能够轻松地将StackOverflow的海量知识库集成到我们的应用中。本文将详细介绍如何使用LangChain的StackExchange组件 在一台Ubuntu计算机上构建Hyperledger Fabric网络 落叶无声9 区块链超级账本Hyperledgerfabric区块链ubuntu构建hyperledgerfabric 在一台Ubuntu计算机上构建HyperledgerFabric网络Hyperledgerfabric是一个开源的区块链应用程序平台,为开发基于区块链的应用程序提供了一个起点。当我们提到HyperledgerFabric网络时,我们指的是使用HyperledgerFabric的正在运行的系统。即使只使用最少数量的组件,部署Fabric网络也不是一件容易的事。Fabric社区创建了一个名为Cello 2.0践行没有你的参与就不完美 x秀丽x 亲爱的伙伴们早上好,今天早上我们开了一次班委竞选的会议,全程只有20多个人参与,宫班本着对大家负责任的态度告诉我们,此次竞选作废,原因是这没有达到2.0的100%参会要求,如果没有大家的参与那么这个班委选出来还有什么意义,这说明选出来的人也是不一定是我们大家心目中认可的那个人,所以为了让大家的这个90天能够更好的激发出自己的的“做”的能力,那么要从第一次竞选班委的会议开始做到100%出席会议,竞选 读书||陶新华《教育中的积极心理学》1—28 流水淙淙2022 读一本好书,尤如和一位高尚者对话,亦能对人的精神进行洗礼。但是若不能和实践结合起来,也只能落到空读书的状态。读书摘要与感想1、塞利格曼在《持续的幸福》一书中提出了幸福2.0理论,提出幸福由5个元素决定——积极情绪、投入的工作和生活、目标和意义、和谐的人际关系、成就感。2、人的大脑皮层在进行智力活动时,都伴有皮下中枢活动,对这些活动进行体验请假,并由此产生了情感解读。人的情绪情感体验总是优先于大脑的 node.js学习 小猿L node.jsnode.js学习vim node.js学习实操及笔记温故node.js,node.js学习实操过程及笔记~node.js学习视频node.js官网node.js中文网实操笔记githubcsdn笔记为什么学node.js可以让别人访问我们编写的网页为后续的框架学习打下基础,三大框架vuereactangular离不开node.jsnode.js是什么官网:node.js是一个开源的、跨平台的运行JavaScript的运行 ES聚合分析原理与代码实例讲解 光剑书架上的书 大厂Offer收割机面试题简历程序员读书硅基计算碳基计算认知计算生物计算深度学习神经网络大数据AIGCAGILLMJavaPython架构设计Agent程序员实现财富自由 ES聚合分析原理与代码实例讲解1.背景介绍1.1问题的由来在大规模数据分析场景中,特别是在使用Elasticsearch(ES)进行数据存储和检索时,聚合分析成为了一个至关重要的功能。聚合分析允许用户对数据集进行细分和分组,以便深入探索数据的结构和模式。这在诸如实时监控、日志分析、业务洞察等领域具有广泛的应用。1.2研究现状目前,ES聚合分析已经成为现代大数据平台的核心组件之一。它支持多种类型的聚 JVM、JRE和 JDK:理解Java开发的三大核心组件 Y雨何时停T Javajava Java是一门跨平台的编程语言,它的成功离不开背后强大的运行环境与开发工具的支持。在Java的生态中,JVM(Java虚拟机)、JRE(Java运行时环境)和JDK(Java开发工具包)是三个至关重要的核心组件。本文将探讨JVM、JDK和JRE的区别,帮助你更好地理解Java的运行机制。1.JVM:Java虚拟机(JavaVirtualMachine)什么是JVM?JVM,即Java虚拟机,是Ja vue3中el-table中点击图片放大时,被表格覆盖 叫我小鹏呀 vue.jsjavascript前端 问题:vue3中el-table中点击图片放大时,被表格覆盖。解决方法:el-image添加preview-teleported vue项目element-ui的table表格单元格合并 酋长哈哈 vue.jselementuijavascript前端 一、合并效果二全部代码exportdefault{name:'CellMerge',data(){return{tableData:[{id:'1',name:'王小虎',amount1:'165',amount2:'3.2',amount3:10},{id:'1',name:'王小虎',amount1:'162',amount2:'4.43',amount3:12},{id:'1',name:' MongoDB知识概括 GeorgeLin98 持久层mongodb MongoDB知识概括MongoDB相关概念单机部署基本常用命令索引-IndexSpirngDataMongoDB集成副本集分片集群安全认证MongoDB相关概念业务应用场景:传统的关系型数据库(如MySQL),在数据操作的“三高”需求以及应对Web2.0的网站需求面前,显得力不从心。解释:“三高”需求:①Highperformance-对数据库高并发读写的需求。②HugeStorage-对海量数 Vue中table合并单元格用法 weixin_30613343 javascriptViewUI 地名结果人名性别{{item.name}}已完成未完成{{item.groups[0].name}}{{item.groups[0].sex}}{{item.groups[son].name}}{{item.groups[son].sex}}exportdefault{data(){return{list:[{name:'地名1',result:'1',groups:[{name:'张三',sex springboot+vue项目实战一-创建SpringBoot简单项目 苹果酱0567 面试题汇总与解析springboot后端java中间件开发语言 这段时间抽空给女朋友搭建一个个人博客,想着记录一下建站的过程,就当做笔记吧。虽然复制zjblog只要一个小时就可以搞定一个网站,或者用cms系统,三四个小时就可以做出一个前后台都有的网站,而且想做成啥样也都行。但是就是要从新做,自己做的意义不一样,更何况,俺就是专门干这个的,嘿嘿嘿要做一个网站,而且从零开始,首先呢就是技术选型了,经过一番思量决定选择-SpringBoot做后端,前端使用Vue做一 uniapp map组件自定义markers标记点 以对_ uni-app学习记录uni-appjavascript前端 需求是根据后端返回数据在地图上显示标记点,并且根据数据状态控制标记点颜色,标记点背景通过两张图片实现控制{{item.options.labelName}}exportdefault{data(){return{storeIndex:0,locaInfo:{longitude:120.445172,latitude:36.111387},markers:[//标点列表{id:1,//标记点idin 基于STM32与Qt的自动平衡机器人:从控制到人机交互的的详细设计流程 极客小张 stm32qt机器人物联网人机交互毕业设计c语言 一、项目概述目标和用途本项目旨在开发一款基于STM32控制的自动平衡机器人,结合步进电机和陀螺仪传感器,实现对平衡机器人的精确控制。该机器人可以用于教育、科研、娱乐等多个领域,帮助用户了解自动控制、机器人运动学等相关知识。技术栈关键词STM32单片机步进电机陀螺仪传感器AD采集电路Qt人机界面实时数据监控二、系统架构系统架构设计本项目的系统架构设计包括以下主要组件:控制单元:STM32单片机传感器 JAVA·一个简单的登录窗口 MortalTom java开发语言学习 文章目录概要整体架构流程技术名词解释技术细节资源概要JavaSwing是Java基础类库的一部分,主要用于开发图形用户界面(GUI)程序整体架构流程新建项目,导入sql.jar包(链接放在了文末),编译项目并运行技术名词解释一、特点丰富的组件提供了多种可视化组件,如按钮(JButton)、文本框(JTextField)、标签(JLabel)、下拉列表(JComboBox)等,可以满足不同的界面设计 Vue( ElementUI入门、vue-cli安装) m0_l5z elementuivue.js 一.ElementUI入门目录:1.ElementUI入门1.1ElementUI简介1.2Vue+ElementUI安装1.3开发示例2.搭建nodejs环境2.1nodejs介绍2.2npm是什么2.3nodejs环境搭建2.3.1下载2.3.2解压2.3.3配置环境变量2.3.4配置npm全局模块路径和cache默认安装位置2.3.5修改npm镜像提高下载速度2.3.6验证安装结果3.运行n 博客网站制作教程 2401_85194651 javamaven 首先就是技术框架:后端:Java+SpringBoot数据库:MySQL前端:Vue.js数据库连接:JPA(JavaPersistenceAPI)1.项目结构blog-app/├──backend/│├──src/main/java/com/example/blogapp/││├──BlogApplication.java││├──config/│││└──DatabaseConfig.java vue+el-table 可输入表格使用上下键进行input框切换 以对_ vue学习记录vue.jsjavascript前端 使用上下键进行完工数量这一列的切换-->//键盘触发事件show(ev,index){letnewIndex;letinputAll=document.querySelectorAll('.table_inputinput');//向上=38if(ev.keyCode==38){if(index==0){//如果是第一行,回到最后一个newIndex=inputAll.length-1}elsei vue + Element UI table动态合并单元格 我家媳妇儿萌哒哒 elementUIvue.js前端javascript 一、功能需求1、根据名称相同的合并工作阶段和主要任务合并这两列,但主要任务内容一样,但要考虑主要任务一样,但工作阶段不一样的情况。(枞向合并)2、落实情况里的定量内容和定性内容值一样则合并。(横向合并)二、功能实现exportdefault{data(){return{tableData:[{name:'a',address:'1',age:'1',six:'2'},{name:'a',addre vue 创建项目报错:command failed: npm install --loglevel error 那鱼、会飞 vue.jsvue-cli3 这个问题其实很好解决,只是很多种情况,逐一排除即可。稳下心来~vuecli3创建项目我的node版本是node14.15.0,(永远不要尝试最新版本)node各种版本下载地址:以往的版本|Node.js(nodejs.org)vue/[email protected]@vue/[email protected](注意vue/cli2和vue/cli3的下载命名有所改变,2是-形式,3是/形式)其实报错 计算机毕业设计PHP仓储综合管理系统(源码+程序+VUE+lw+部署) java毕设程序源码王哥 php课程设计vue.js 该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流项目运行环境配置:phpStudy+Vscode+Mysql5.7+HBuilderX+Navicat11+Vue+Express。项目技术:原生PHP++Vue等等组成,B/S模式+Vscode管理+前后端分离等等。环境需要1.运行环境:最好是小皮phpstudy最新版,我们在这个版本上开发的。其他版本理论上也可以。2.开发 使用由 Python 编写的 lxml 实现高性能 XML 解析 hunyxv python笔记pythonxml 转载自:文章lxml简介Python从来不出现XML库短缺的情况。从2.0版本开始,它就附带了xml.dom.minidom和相关的pulldom以及SimpleAPIforXML(SAX)模块。从2.4开始,它附带了流行的ElementTreeAPI。此外,很多第三方库可以提供更高级别的或更具有python风格的接口。尽管任何XML库都足够处理简单的DocumentObjectModel(DOM 信息系统安全相关概念(上) YuanDaima2048 课程笔记基础概念安全信息安全笔记 文章总览:YuanDaiMa2048博客文章总览下篇:信息系统安全相关概念(下)信息系统安全相关概念[上]信息系统概述信息系统信息系统架构信息系统发展趋势:信息系统日趋大型化、复杂化信息系统面临的安全威胁信息系统安全架构设计--以云计算为例信息系统安全需求及安全策略自主访问控制策略DAC强制访问控制策略MAC信息系统概述信息系统用于收集、存储和处理数据以及传递信息、知识和数字产品的一组集成组件。几 字节二面 Redstone Monstrosity 前端面试 1.假设你是正在面试前端开发工程师的候选人,面试官让你详细说出你上一段实习过程的收获和感悟。在上一段实习过程中,我获得了宝贵的实践经验和深刻的行业洞察,以下是我的主要收获和感悟:一、专业技能提升框架应用熟练度:通过实际项目,我深入掌握了React、Vue等前端框架的使用,不仅提升了编码效率,还学会了如何根据项目需求选择合适的框架。问题解决能力:在实习期间,我遇到了许多预料之外的技术难题。通过查阅文 HarmonyOS开发实战( Beta5.0)搜索框热搜词自动切换 让开,我要吃人了 OpenHarmonyHarmonyOS鸿蒙开发harmonyos华为鸿蒙移动开发鸿蒙系统前端开发语言 鸿蒙HarmonyOS开发往期必看:HarmonyOSNEXT应用开发性能实践总结最新版!“非常详细的”鸿蒙HarmonyOSNext应用开发学习路线!(从零基础入门到精通)介绍本示例介绍使用TextInput组件与Swiper组件实现搜索框内热搜词自动切换。效果图预览使用说明页面顶部搜索框内热搜词条自动切换,编辑搜索框时自动隐藏。实现思路使用TextInput实现搜索框TextInput({te vue render 函数详解 (配参数详解) 你的眼睛會笑 vue2vue.jsjavascript前端 vuerender函数详解(配参数详解)在Vue3中,`render`函数被用来代替Vue2中的模板语法。它接收一个h函数(或者是`createElement`函数的别名),并且返回一个虚拟DOM。render函数的语法结构如下:render(h){returnh('div',{class:'container'},'Hello,World!')}在上面的示例中,我们使用h函数创建了一个div元素 内存保护学习(一):tc27x的内存保护MPU设置浅析(个人理解) 剑从东方起 链接文件及功能安全开发语言c语言 目录一、背景二、Tc27x相关寄存器1、注意点2、注意几个强相关寄存器1)、数据保护范围寄存器2)、代码保护范围寄存器3)、保护集启用寄存器命名约定4)、PSW(每个核都有一个)5)、SYSCON三、使用方法1、内存方面2、在ECUM里面初始化MPU3、OS回调CBK检查4、机理5、补充点一、背景根据低ASIL等级开发的软件组件可能会错误地访问具有较高ASIL等级的软件组件的内存区域,从而产生干扰 前端代码上传文件 余生逆风飞翔 前端javascript开发语言 点击上传文件import{ElNotification}from'element-plus'import{API_CONFIG}from'../config/index.js'import{UploadFilled}from'@element-plus/icons-vue'import{reactive}from'vue'import{BASE_URL}from'../config/index'i VUE3 + xterm + nestjs实现web远程终端 或 连接开启SSH登录的路由器和交换机。 焚木灵 node.jsvue 可远程连接系统终端或开启SSH登录的路由器和交换机。相关资料:xtermjs/xterm.js:Aterminalfortheweb(github.com)后端实现(NestJS):1、安装依赖:npminstallnode-ssh@nestjs/websockets@nestjs/platform-socket.io2、我们将创建一个名为RemoteControlModule的NestJS模块, TOMCAT在POST方法提交参数丢失问题 357029540 javatomcatjsp 摘自http://my.oschina.net/luckyi/blog/213209 昨天在解决一个BUG时发现一个奇怪的问题,一个AJAX提交数据在之前都是木有问题的,突然提交出错影响其他处理流程。 检查时发现页面处理数据较多,起初以为是提交顺序不正确修改后发现不是由此问题引起。于是删除掉一部分数据进行提交,较少数据能够提交成功。 恢复较多数据后跟踪提交FORM DATA ,发现数 在MyEclipse中增加JSP模板 删除-2008-08-18 ljy325 jspxmlMyEclipse 在D:\Program Files\MyEclipse 6.0\myeclipse\eclipse\plugins\com.genuitec.eclipse.wizards_6.0.1.zmyeclipse601200710\templates\jsp 目录下找到Jsp.vtl,复制一份,重命名为jsp2.vtl,然后把里面的内容修改为自己想要的格式,保存。 然后在 D:\Progr JavaScript常用验证脚本总结 eksliang JavaScriptjavaScript表单验证 转载请出自出处:http://eksliang.iteye.com/blog/2098985 下面这些验证脚本,是我在这几年开发中的总结,今天把他放出来,也算是一种分享吧,现在在我的项目中也在用!包括日期验证、比较,非空验证、身份证验证、数值验证、Email验证、电话验证等等...! &nb 微软BI(4) 18289753290 微软BI SSIS 1) Q:查看ssis里面某个控件输出的结果: A MessageBox.Show(Dts.Variables["v_lastTimestamp"].Value.ToString()); 这是我们在包里面定义的变量 2):在关联目的端表的时候如果是一对多的关系,一定要选择唯一的那个键作为关联字段。 3) Q:ssis里面如果将多个数据源的数据插入目的端一 定时对大数据量的表进行分表对数据备份 酷的飞上天空 大数据量 工作中遇到数据库中一个表的数据量比较大,属于日志表。正常情况下是不会有查询操作的,但如果不进行分表数据太多,执行一条简单sql语句要等好几分钟。。 分表工具:linux的shell + mysql自身提供的管理命令 原理:使用一个和原表数据结构一样的表,替换原表。 linux shell内容如下: =======================开始  本质的描述与因材施教 永夜-极光 感想随笔 不管碰到什么事,我都下意识的想去探索本质,找寻一个最形象的描述方式。 我坚信,世界上对一件事物的描述和解释,肯定有一种最形象,最贴近本质,最容易让人理解 & 很迷茫。。。 随便小屋 随笔 小弟我今年研一,也是从事的咱们现在最流行的专业(计算机)。本科三流学校,为了能有个更好的跳板,进入了考研大军,非常有幸能进入研究生的行业(具体学校就不说了,怕把学校的名誉给损了)。 先说一下自身的条件,本科专业软件工程。主要学习就是软件开发,几乎和计算机没有什么区别。因为学校本身三流,也就是让老师带着学生学点东西,然后让学生毕业就行了。对专业性的东西了解的非常浅。就那学的语言来说 23种设计模式的意图和适用范围 aijuans 设计模式 Factory Method 意图 定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使一个类的实例化延迟到其子类。 适用性 当一个类不知道它所必须创建的对象的类的时候。 当一个类希望由它的子类来指定它所创建的对象的时候。 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。 Abstr Java中的synchronized和volatile aoyouzi javavolatilesynchronized 说到Java的线程同步问题肯定要说到两个关键字synchronized和volatile。说到这两个关键字,又要说道JVM的内存模型。JVM里内存分为main memory和working memory。 Main memory是所有线程共享的,working memory则是线程的工作内存,它保存有部分main memory变量的拷贝,对这些变量的更新直接发生在working memo js数组的操作和this关键字 百合不是茶 js数组操作this关键字 js数组的操作; 一:数组的创建: 1、数组的创建 var array = new Array(); //创建一个数组 var array = new Array([size]); //创建一个数组并指定长度,注意不是上限,是长度 var arrayObj = new Array([element0[, element1[, ...[, elementN]]] 别人的阿里面试感悟 bijian1013 面试分享工作感悟阿里面试 原文如下:http://greemranqq.iteye.com/blog/2007170 一直做企业系统,虽然也自己一直学习技术,但是感觉还是有所欠缺,准备花几个月的时间,把互联网的东西,以及一些基础更加的深入透析,结果这次比较意外,有点突然,下面分享一下感受吧! &nb 淘宝的测试框架Itest Bill_chen springmaven框架单元测试JUnit Itest测试框架是TaoBao测试部门开发的一套单元测试框架,以Junit4为核心, 集合DbUnit、Unitils等主流测试框架,应该算是比较好用的了。 近期项目中用了下,有关itest的具体使用如下: 1.在Maven中引入itest框架: <dependency> <groupId>com.taobao.test</groupId&g 【Java多线程二】多路条件解决生产者消费者问题 bit1129 java多线程 package com.tom; import java.util.LinkedList; import java.util.Queue; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.locks.Condition; import java.util.concurrent.loc 汉字转拼音pinyin4j 白糖_ pinyin4j 以前在项目中遇到汉字转拼音的情况,于是在网上找到了pinyin4j这个工具包,非常有用,别的不说了,直接下代码: import java.util.HashSet; import java.util.Set; import net.sourceforge.pinyin4j.PinyinHelper; import net.sourceforge.pinyin org.hibernate.TransactionException: JDBC begin failed解决方案 bozch ssh数据库异常DBCP org.hibernate.TransactionException: JDBC begin failed: at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:68) at org.hibernate.impl.SessionImp java-并查集(Disjoint-set)-将多个集合合并成没有交集的集合 bylijinnan java import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.ut Java PrintWriter打印乱码 chenbowen00 java 一个小程序读写文件,发现PrintWriter输出后文件存在乱码,解决办法主要统一输入输出流编码格式。 读文件: BufferedReader 从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取。 可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。 通常,Reader 所作的每个读取请求都会导致对基础字符或字节流进行相应的读取请求。因 [天气与气候]极端气候环境 comsci 环境 如果空间环境出现异变...外星文明并未出现,而只是用某种气象武器对地球的气候系统进行攻击,并挑唆地球国家间的战争,经过一段时间的准备...最大限度的削弱地球文明的整体力量,然后再进行入侵...... 那么地球上的国家应该做什么样的防备工作呢? &n oracle order by与union一起使用的用法 daizj UNIONoracleorder by 当使用union操作时,排序语句必须放在最后面才正确,如下: 只能在union的最后一个子查询中使用order by,而这个order by是针对整个unioning后的结果集的。So: 如果unoin的几个子查询列名不同,如 Sql代码 select supplier_id, supplier_name from suppliers UNI zeus持久层读写分离单元测试 deng520159 单元测试 本文是zeus读写分离单元测试,距离分库分表,只有一步了.上代码: 1.ZeusMasterSlaveTest.java package com.dengliang.zeus.webdemo.test; import java.util.ArrayList; import java.util.List; import org.junit.Assert; import org.j Yii 截取字符串(UTF-8) 使用组件 dcj3sjt126com yii 1.将Helper.php放进protected\components文件夹下。 2.调用方法: Helper::truncate_utf8_string($content,20,false); //不显示省略号 Helper::truncate_utf8_string($content,20); //显示省略号 &n 安装memcache及php扩展 dcj3sjt126com PHP 安装memcache tar zxvf memcache-2.2.5.tgz cd memcache-2.2.5/ /usr/local/php/bin/phpize (?) ./configure --with-php-confi JsonObject 处理日期 feifeilinlin521 javajsonJsonOjbectJsonArrayJSONException 写这边文章的初衷就是遇到了json在转换日期格式出现了异常 net.sf.json.JSONException: java.lang.reflect.InvocationTargetException 原因是当你用Map接收数据库返回了java.sql.Date 日期的数据进行json转换出的问题话不多说 直接上代码 &n Ehcache(06)——监听器 234390216 监听器listenerehcache 监听器 Ehcache中监听器有两种,监听CacheManager的CacheManagerEventListener和监听Cache的CacheEventListener。在Ehcache中,Listener是通过对应的监听器工厂来生产和发生作用的。下面我们将来介绍一下这两种类型的监听器。 activiti 自带设计器中chrome 34版本不能打开bug的解决 jackyrong Activiti 在acitivti modeler中,如果是chrome 34,则不能打开该设计器,其他浏览器可以, 经证实为bug,参考 http://forums.activiti.org/content/activiti-modeler-doesnt-work-chrome-v34 修改为,找到 oryx.debug.js 在最头部增加 if (!Document. 微信收货地址共享接口-终极解决 laotu5i0 微信开发 最近要接入微信的收货地址共享接口,总是不成功,折腾了好几天,实在没办法网上搜到的帖子也是骂声一片。我把我碰到并解决问题的过程分享出来,希望能给微信的接口文档起到一个辅助作用,让后面进来的开发者能快速的接入,而不需要像我们一样苦逼的浪费好几天,甚至一周的青春。各种羞辱、谩骂的话就不说了,本人还算文明。 如果你能搜到本贴,说明你已经碰到了各种 ed 关于人才 netkiller.github.com 工作面试招聘netkiller人才 关于人才 每个月我都会接到许多猎头的电话,有些猎头比较专业,但绝大多数在我看来与猎头二字还是有很大差距的。 与猎头接触多了,自然也了解了他们的工作,包括操作手法,总体上国内的猎头行业还处在初级阶段。 总结就是“盲目推荐,以量取胜”。 目前现状 许多从事人力资源工作的人,根本不懂得怎么找人才。处在人才找不到企业,企业找不到人才的尴尬处境。 企业招聘,通常是需要用人的部门提出招聘条件,由人 搭建 CentOS 6 服务器 - 目录 rensanning centos (1) 安装CentOS ISO(desktop/minimal)、Cloud(AWS/阿里云)、Virtualization(VMWare、VirtualBox) 详细内容 (2) Linux常用命令 cd、ls、rm、chmod...... 详细内容 (3) 初始环境设置 用户管理、网络设置、安全设置...... 详细内容 (4) 常驻服务Daemon 【求助】mongoDB无法更新主键 toknowme mongodb Query query = new Query(); query.addCriteria(new Criteria("_id").is(o.getId())); &n jquery 页面滚动到底部自动加载插件集合 xp9802 jquery 很多社交网站都使用无限滚动的翻页技术来提高用户体验,当你页面滑到列表底部时候无需点击就自动加载更多的内容。下面为你推荐 10 个 jQuery 的无限滚动的插件: 1. jQuery ScrollPagination jQuery ScrollPagination plugin 是一个 jQuery 实现的支持无限滚动加载数据的插件。 2. jQuery Screw S 按字母分类: ABCDEFGHIJKLMNOPQRSTUVWXYZ其他
因为 Vue 只有在浏览器解析和标准化 HTML 后才能获取模版内容。尤其像这些元素
<table> <my-row>...my-row> table> <table> <tr is="my-row">tr> table>
使用组件时,大多数可以传入到 Vue 构造器中的选项可以在注册组件时使用,有一个例外: data 必须是函数。 实际上
//这样会报错,提示data必须是一个函数 Vue.component('my-component', { template: '{{ message }}', data: { message: 'hello' } })
<div id="example-2"> <simple-counter>simple-counter> <simple-counter>simple-counter> <simple-counter>simple-counter> div>
var data = { counter: 0 } Vue.component('simple-counter', { template: '{{ counter }}', // data 是一个函数,因此 Vue 不会警告, // 但是我们为每一个组件返回了同一个对象引用,所以改变其中一个会把其他都改变了 data: function () { return data } }) new Vue({ el: '#example-2' })
避免出现同时改变数据的情况
//返回一个新的对象,而不是返回同一个data对象引用 data: function () { return { //字面量写法会创建新对象 counter: 0 } }
组件意味着协同工作,通常父子组件会是这样的关系:
组件 A 在它的模版中使用了组件 B 。它们之间必然需要相互通信
父组件要给子组件传递数据,子组件需要将它内部发生的事情告知给父组件
然而,在一个良好定义的接口中尽可能将父子组件解耦是很重要的。这保证了每个组件可以在相对隔离的环境中书写和理解,也大幅提高了组件的可维护性和可重用性。
在 Vue.js 中,父子组件的关系可以总结为 props down, events up 。 父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。看看它们是怎么工作的。
使用prop传递数据
组件实例的作用域是孤立的。这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。
使用 props 把数据传给子组件。
prop 是父组件用来传递数据的一个自定义属性
子组件需要显式地用 props 选项声明 “prop”
<div id="example-2"> <child message="hello!">child> div>
Vue.component('child', { // 声明 props,用数组形式的对象 props: ['message'], // 就像 data 一样,prop 可以用在模板内 // 同样也可以在 vm 实例中像 “this.message” 这样使用 template: '{{ message }}' }); new Vue({ el: '#example-2' })
用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件
<div id="example-2"> <input v-model="parentMsg"> <br> <child v-bind:my-message="parentMsg">child> div>
Vue.component('child', { // 声明 props props: ['my-message'], template: '{{ myMessage }}' //如果写my-message会报错,需要转换为驼峰写法 }); new Vue({ el: '#example-2', data: { parentMsg: '' } })
HTML 特性不区分大小写。当使用非字符串模版时,prop的名字形式会从 camelCase 转为 kebab-case(短横线隔开)
在JavaScript里面使用驼峰写法,但是在html里面需要转成短横线写法
反之亦然,vue会自动处理来自html的短横线写法转为驼峰写法
<comp some-prop="1">comp> <comp v-bind:some-prop="1">comp>
prop 是单向绑定的
当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解。
每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你不应该在子组件内部改变 prop 。如果你这么做了,Vue 会在控制台给出警告。
通常有两种改变 prop 的情况:
prop 作为初始值传入,子组件之后只是将它的初始值作为本地数据的初始值使用
定义一个局部 data 属性,并将 prop 的初始值作为局部数据的初始值。
<div id="example-2"> <child initial-counter="10">child> div>
Vue.component('child', { props: ['initialCounter'],//这里用驼峰写法 data: function () { //转为一个局部变量,写一个data对象给组件使用 return {counter: this.initialCounter} }, template: '{{ counter }}' }); new Vue({ el: '#example-2' })
prop 作为需要被转变的原始值传入。
定义一个 computed 属性,此属性从 prop 的值计算得出。
//例子没有写完,但是根据第一个例子可以知道利用computed的手法原理其实跟写一个data差不多 props: ['size'], computed: { normalizedSize: function () { return this.size.trim().toLowerCase() } }
注意在 JavaScript 中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它会影响父组件的状态。
组件可以为 props 指定验证要求,当组件给其他人使用时这很有用。
Vue.component('example', { props: { // 基础类型检测 (`null` 意思是任何类型都可以) propA: Number, // 多种类型 propB: [String, Number], // 必传且是字符串 propC: { type: String, required: true }, // 数字,有默认值 propD: { type: Number, default: 100 }, // 数组/对象的默认值应当由一个工厂函数返回 propE: { type: Object, default: function () { return { message: 'hello' } } }, // 自定义验证函数 propF: { validator: function (value) { return value > 10 } } } })
每个 Vue 实例都实现了事件接口(Events interface)
使用 $on(eventName) 监听事件
使用 $emit(eventName) 触发事件
父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
<div id="counter-event-example"> <p>{{ total }}p> <button-counter v-on:increment1="incrementTotal">button-counter> <button-counter v-on:increment1="incrementTotal">button-counter> div>
Vue.component('button-counter', { //监听click事件,处理程序为increment(子组件定义的方法) template: '{{ counter }}', //每一个counter都是独立的对象属性 data: function () { return { counter: 0 } }, //子组件的方法 methods: { increment: function () { this.counter += 1; //在子组件里面直接触发之前监听的increment1事件来执行父组件的方法 this.$emit('increment1'); } }, }) new Vue({ el: '#counter-event-example', data: { total: 0 }, //父组件的方法 methods: { incrementTotal: function () { this.total += 1 } } })
1.组件之间因为作用域不同的关系,所以相互独立,所以子组件想要使用父组件的方法的话需要做一个新的监听映射
<my-component v-on:click.native="doTheThing">my-component>
自定义事件也可以用来创建自定义的表单输入组件,使用 v-model 来进行数据双向绑定。所以要让组件的 v-model 生效,它必须:
接受一个 value 属性
在有新的 value 时触发 input 事件
<input v-model="something"> <input v-bind:value="something" v-on:input="something = $event.target.value">
一个非常简单的货币输入:
<currency-input v-model="price">currency-input>
Vue.component('currency-input', { template: '\ \ $\ \ \ ', props: ['value'], //父组件将绑定的value传给子组件 methods: { // 不是直接更新值,而是使用此方法来对输入值进行格式化和位数限制 updateValue: function (value) { var formattedValue = value //对值进行处理 // 删除两侧的空格符 .trim() // 保留 2 小数位和2位数 .slice(0, value.indexOf('.') + 3) // 如果值不统一,手动覆盖以保持一致,为了保持输入框显示内容跟格式化内容一致 if (formattedValue !== value) { //因为注册是一个input元素,所以this.$refs 就是input元素 this.$refs.input.value = formattedValue } //手动触发input事件,将格式化后的值传过去,这是最终显示输入框的输出 this.$emit('input', Number(formattedValue)) } } }) //实例化vue实例的 new Vue({ el: '#aa', //要绑定一个vue实例,例如包裹一个id为aa的div data:{ price:'' //v-model要有数据源 } })
ref 被用来给元素或子组件注册引用信息。引用信息会根据父组件的 $refs 对象进行注册。如果在普通的DOM元素上使用,引用信息就是元素; 如果用在子组件上,引用信息就是组件实例 ref
这是一个比较完整的例子:
<div id="app"> <currency-input label="Price" v-model="price" >currency-input> <currency-input label="Shipping" v-model="shipping" >currency-input> <currency-input label="Handling" v-model="handling" >currency-input> <currency-input label="Discount" v-model="discount" >currency-input> <p>Total: ${{ total }}p> div>
Vue.component('currency-input', { template: '\ \ {{ label }}\ $\ \ \ ', props: { //多个prop传递,因为prop是对象,只要是对象格式就行 value: { type: Number, default: 0 }, label: { type: String, default: '' } }, mounted: function () { //这是vue的过渡状态,暂时忽略不影响理解 this.formatValue() }, methods: { updateValue: function (value) { var result = currencyValidator.parse(value, this.value) if (result.warning) { // 这里也使用了$refs获取引用注册信息 this.$refs.input.value = result.value } this.$emit('input', result.value) }, formatValue: function () { this.$refs.input.value = currencyValidator.format(this.value) //这里注意下,这个this是prop传递过来的,也相当于这个组件作用域 }, selectAll: function (event) { //event可以获取原生的js事件 // Workaround for Safari bug // http://stackoverflow.com/questions/1269722/selecting-text-on-focus-using-jquery-not-working-in-safari-and-chrome setTimeout(function () { event.target.select() }, 0) } } }) new Vue({ el: '#app', data: { price: 0, shipping: 0, handling: 0, discount: 0 }, computed: { total: function () { return (( this.price * 100 + this.shipping * 100 + this.handling * 100 - this.discount * 100 ) / 100).toFixed(2) } } })
在简单的场景下,使用一个空的 Vue 实例作为中央事件总线:
var bus = new Vue() // 触发组件 A 中的事件 bus.$emit('id-selected', 1) /* 通过on来监听子组件的事件来实现传递 */ // 在组件 B 创建的钩子中监听事件 bus.$on('id-selected', function (id) { // ... })
为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板。这个过程被称为 内容分发 (或 “transclusion” 如果你熟悉 Angular)
组件作用域简单地说是:父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。假定 someChildProperty 是子组件的属性,上例不会如预期那样工作。父组件模板不应该知道子组件的状态。
<child-component v-show="someChildProperty">child-component>
如果要绑定子组件内的指令到一个组件的根节点,应当在它的模板内这么做:
Vue.component('child-component', { // 有效,因为是在正确的作用域内 template: 'Child', data: function () { return { //因为这个属性在当前组件内编译(创建了) someChildProperty: true } } })
类似地,分发内容是在父组件作用域内编译。
除非子组件模板包含至少一个 插口,否则父组件的内容将会被丢弃。
当子组件模板只有一个没有属性的 slot 时,父组件整个内容片段将插入到 slot 所在的 DOM 位置,并替换掉 slot 标签本身。
备用内容在子组件的作用域内编译,并且只有在宿主元素为空,且没有要插入的内容时才显示备用内容。
<div id="aa"> <h1>我是父组件的标题h1> <my-component>my-component> <my-component> <p>这是一些初始内容p> <p>这是更多的初始内容p> my-component> div>
Vue.component('my-component', { //my-component 组件有下面模板 template: '\ \ 我是子组件的标题 \ \ //有slot插口,所以没有被父组件丢弃 只有在没有要分发的内容时才会显示。\ \ \ ' }) new Vue({ el: '#aa', })
渲染结果:
<div id="aa"><h1>我是父组件的标题h1> <div> <h2>我是子组件的标题h2> 只有在没有要分发的内容时才会显示。 div> <div> <h2>我是子组件的标题h2> <p>这是一些初始内容p> <p>这是更多的初始内容p> div> div>
元素可以用一个特殊的属性 name 来配置如何分发内容。多个 slot 可以有不同的名字。具名 slot 将匹配内容片段中有对应 slot 特性的元素。
仍然可以有一个匿名 slot ,它是默认 slot ,作为找不到匹配的内容片段的备用插槽。如果没有默认的 slot ,这些找不到匹配的内容片段将被抛弃。
<div id="aa"> <app-layout> <h1 slot="header">这里可能是一个页面标题h1> <p>主要内容的一个段落。p> <p>另一个主要段落。p> <p slot="footer">这里有一些联系信息p> app-layout> div>
Vue.component('app-layout', { template: '\ \ \ //找到名字叫header的slot之后替换内容,这里替换的是整个DOM \ \ \ //因为slot没有属性,会将内容插入到slot的所在的DOM位置 \ \ \ \ ' }); new Vue({ el: '#aa', })
渲染结果为:
<div class="container"> <header> <h1>这里可能是一个页面标题h1> header> <main> <p>主要内容的一个段落。p> <p>另一个主要段落。p> main> <footer> <p>这里有一些联系信息p> footer> div>
作用域插槽是一种特殊类型的插槽,用作使用一个(能够传递数据到)可重用模板替换已渲染元素。
在子组件中,只需将数据传递到插槽,就像你将 prop 传递给组件一样
在父级中,具有特殊属性 scope 的 元素,表示它是作用域插槽的模板。scope 的值对应一个临时变量名,此变量接收从子组件中传递的 prop 对象
<div id="parent" class="parent"> <child> <template scope="props"> <span>hello from parentspan> <span>{{ props.text }}span> template> child> div>
Vue.component('child', { props: ['props'], //这个写不写都可以,作用域插槽固定会接收prop对象,而且这个prop对象是肯定存在的 template: '\ \ \ //在子组件里直接将数据传递给slot \ ' }); new Vue({ el: '#parent', })
渲染结果:
<div class="parent"> <div class="child"> <span>hello from parentspan> <span>hello from childspan> div> div>
另外一个例子,作用域插槽更具代表性的用例是列表组件,允许组件自定义应该如何渲染列表每一项
<div id="parent"> <my-awesome-list :items="items"> <template slot="item" scope="props"> <li class="my-fancy-item">{{ props.text }}li> template> my-awesome-list> div>
Vue.component('my-awesome-list', { props:['items'], //需要声明prop为items,需要是为下面的循环遍历的items的数据源做设定,位置3 template: '\ \ \ //在slot中,循环遍历输出items的text,位置4 \ \ ' }); new Vue({ el: '#parent', data : { items:[ //初始化items数据 {text:"aa"}, {text:"bb"} ] } })
位置1,实现了一个组件的prop绑定,prop需要在组件里面声明,这里绑定的是items,这是要将父组件的items传递到子组件,所以在位置3里面需要声明,在vue实例要初始化
位置2,这里scope的props是代表作用域插槽接收来自prop对象的数据,props.text是代表每一个li要输出的是prop对象的text属性
位置3,在组件里声明props,为了接收父组件绑定的items属性,然后将其给位置4的循环使用
位置4,这里绑定了text属性,就是前呼位置2里面输出的prop对象的text属性
多个组件可以使用同一个挂载点,然后动态地在它们之间切换。使用保留的 元素,动态地绑定到它的 is 特性
var vm = new Vue({ el: '#example', data: { currentView: 'home' //默认值 }, components: { //根据不同的值进行不同的组件切换,这里用components写法 home: { /* ... */ }, posts: { /* ... */ }, archive: { /* ... */ } } })
<component v-bind:is="currentView"> component>
如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。为此可以添加一个 keep-alive 指令参数
<keep-alive> <component :is="currentView"> component> keep-alive>
在编写组件时,记住是否要复用组件有好处。一次性组件跟其它组件紧密耦合没关系,但是可复用组件应当定义一个清晰的公开接口。Vue 组件的 API 来自三部分 - props, events 和 slots :
Props 允许外部环境传递数据给组件
Events 允许组件触发外部环境的副作用
Slots 允许外部环境将额外的内容组合在组件中。
<my-component :foo="baz" :bar="qux" @event-a="doThis" @event-b="doThat" > <img slot="icon" src="..."> <p slot="main-text">Hello!p> my-component>
尽管有 props 和 events ,但是有时仍然需要在 JavaScript 中直接访问子组件。为此可以使用 ref 为子组件指定一个索引 ID 。
<div id="parent"> <user-profile ref="profile">user-profile> div>
var parent = new Vue({ el: '#parent' }) // 访问子组件 var child = parent.$refs.profile
当 ref 和 v-for 一起使用时, ref 是一个数组或对象,包含相应的子组件。 $refs 只在组件渲染完成后才填充,并且它是非响应式的。它仅仅作为一个直接访问子组件的应急方案——应当避免在模版或计算属性中使用 $refs 。 ref 被用来给元素或子组件注册引用信息。引用信息会根据父组件的 $refs 对象进行注册。如果在普通的DOM元素上使用,引用信息就是元素; 如果用在子组件上,引用信息就是组件实例 ref
当 ref 和 v-for 一起使用时, ref 是一个数组或对象,包含相应的子组件。
$refs 只在组件渲染完成后才填充,并且它是非响应式的。它仅仅作为一个直接访问子组件的应急方案——应当避免在模版或计算属性中使用 $refs 。
当注册组件(或者 props)时,可以使用 kebab-case ,camelCase ,或 TitleCase 。Vue 不关心这个。
在 HTML 模版中,请使用 kebab-case 形式:
// 在组件定义中 components: { // 使用 kebab-case 形式注册--横线写法 'kebab-cased-component': { /* ... */ }, // register using camelCase --驼峰写法 'camelCasedComponent': { /* ... */ }, // register using TitleCase --标题写法 'TitleCasedComponent': { /* ... */ } }
<kebab-cased-component>kebab-cased-component> <camel-cased-component>camel-cased-component> <title-cased-component>title-cased-component>
组件在它的模板内可以递归地调用自己,不过,只有当它有 name 选项时才可以
当你利用Vue.component全局注册了一个组件, 全局的ID作为组件的 name 选项,被自动设置.
//组件可以用name来写名字 name: 'unique-name-of-my-component' //也可以在创建的时候默认添加名字 Vue.component('unique-name-of-my-component', { // ... }) //如果同时使用的话,递归的时候就会不断递归自己,导致溢出 name: 'stack-overflow', template: ''
尽管在 Vue 中渲染 HTML 很快,不过当组件中包含大量静态内容时,可以考虑使用 v-once 将渲染结果缓存起来,就像这样:
Vue.component('terms-of-service', { template: '\ \ Terms of Service\ ... a lot of static content ...\ \ ' })
v-once只渲染元素和组件一次。随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过。这可以用于优化更新性能。