🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 开始 start ``` component 组成的,构成的 template 模版 methods 方法 watch 监听,观察 prop 维持,支持 ``` ![](https://box.kancloud.cn/dc2a6d886456ed931a2e0977d510f342_743x440.png)![](https://box.kancloud.cn/6628196cedbac8f930c15c3529fd5a63_676x422.png) ![](https://box.kancloud.cn/646dcd79659fe5de7d19355e2fb9eb94_843x430.png) [TOC] ***** ## 全局注册 Vue记得`V`需要大写我们把需要的东西封装进去就成了一个组件 template 是一个模版下面封装了一个button ``` //这是一个全局组成组件 Vue.component('button-counter',{ data: function( ) { return{ count : 0 } }, template:'<button v-on:click = "count++">{{ count }} 个 </button>' }) ``` 我们可以通过new Vue 创建的Vue根实例把组件作为自定义元素来使用 因为组件是可复用的 Vue 实例,所以它们与`new Vue`接收相同的选项,例如`data`、`computed`、`watch`、`methods`以及生命周期钩子等。仅有的例外是像`el`这样根实例特有的选项。 ``` <div id='app'> <button-counter></button-counter> </div> new Vue({ el: '#app'}) 这里的el就是Element ``` 另一种注册方法 通过全局API `Vue.extend ()` ***示例*** ``` // 注册 var MyComponent = Vue.extend({ template: '<div>A custom component!</div>' }); // 注册 Vue.component('my-component', MyComponent); var vm = new Vue({ el: '#example', data: { } }) ``` 用法:使用基础 Vue 构造器,创建一个“子类”。参数是一个`包含组件选项的对象`。 `data`选项是特例,需要注意 - 在`Vue.extend()`中它必须是`函数`。 组件你可以复用任何次数不限,你每用一次组件,就会有一个它的新**实例**被创建 ## 局部注册 类似于JavaScript的定义一个对象,不需要全局注册,仅仅在其作用域中可用的组件 ``` var ComponentA = {自定义} var ComponentB = {自定义} //然后在`componets`中定义你需要用到的 new Vue({ el:'#app' componets:{ 'componets-a' = ComponetsA, 'componets-b' = ComponetsB } }) ``` 注意,**局部注册的组件在子组件中*无法访问***。 ## 模块系统 模块系统中的局部注册方法在局部注册这些组件之前,你需要预先导入每个需要用到的组件。例如,在假想的`ComponentB.js`或`ComponentB.vue`文件中: ``` import ComponentA from './ComponentA' import ComponentC from './ComponentC' export default { components: { ComponentA, ComponentC }, // ... } ``` 现在A和C都能在B中应用了 ### ⚠️data必须是一个函数 我们定义一个组件的时候`data`并不会直接提供一个对象给我们。因为他需要复用每使用一次就会创建一个新实例出来从而不会干扰到其他组件。每个实例可以维护一份被返回对象的独立的拷贝 ``` data: function () { return { count: 0 } } ``` ### DOM 模板解析注意事项 像`<ul>、<ol>、<table>、<select>`这样的元素里允许包含的元素有限制,而另一些像`<option>`这样的元素只能出现在某些特定元素的内部。 例如: ~~~ table> <my-row>...</my-row> </table> ~~~ 自定义组件`<my-row>`会被当作无效的内容,因此会导致错误的渲染结果。变通的方案是使用特殊的`is`特性: ~~~ <table> <tr is="my-row"></tr> </table> ~~~ **应当注意,如果使用来自以下来源之一的字符串模板,则没有这些限制:** * `<script type="text/x-template">` * `JavaScript`内联模板字符串 * `.vue`组件 因此,请尽可能使用字符串模板。 ## Prop书写规范 ![](https://box.kancloud.cn/41d8417fa323e5ff43402d2348efe5a0_612x696.png) ![](https://box.kancloud.cn/de945e6226ea46d0bba3bab2e85a9b48_342x240.png) ## Prop向子组件传递数据 `Prop`使你可以在组件中注册一些自定义特性当一个值传入`Prop`时它就变成了那个组件实例的一个属性,一个组件可以拥有任意数量的`Prop` ``` Vue.component('blog-post', { props: ['title'], template: '<p> {{ title }} </p>' }) <blog-post title></blog-post> ``` 假如 `data` 中有一个数组你想渲染每一个组件 ``` new Vue({ el: '#app', data:{ posts: { { id: 1, title: 'you' } { id: 2, title: 'he'} { id: 3, title: 'she'} } } }) //初体验中有使用到过一次 <blog-post v-for = 'post in posts' v-bind:key = 'post.id' v-bind:title = 'post.title'> ... </blog-post> ``` 使用`v-bind`来做render是非常有用的 当组件越来越复杂时为每一个相关信息定义一个prop会变得很麻烦 ``` <blog-post v-bind:post = 'post'></blog-post> template:' <div class='blog-post'> <h3>{{ post.title }}</h3> <div v-html = 'post.content'></div> </div> ' ``` **每个组件必须只有一个根元素**你可以将模板的内容包裹在一个父元素内 ``` <div class ='blog-post'> <h3>{{ title }}</h3> <div v-html='content'></div> </div. ``` 这是wacth监听事件以及computed的使用 原本跟着慕课网敲的但是报错不知道为哈子他可以单括号输出我就不行他`{ msg }` 我`{{ msg }}`;当你在`new Vue`外声明变量时你里面调用如果只修改外面变量输出内容是不会改变的;你需要触发到`new Vue`里的this.msg才会进行改变 ``` <div id="app" > {{msg1}} </div> var arr = 'nice' var app = new Vue({ el:'#app', data:{ msg:'hellow' }, watch:{ msg:function(newval,oldval){ console.log('newval' + newval); console.log('oldval' + oldval); } }, computed:{ msg1:function(){ return this.msg + arr } } }) ``` watch通常只监听一个事件,而computed是可以监听多个的但是需要在`new Vue`里才能,外头声明的变量不会作出改变 ## 动态Prop ~~~ <div> <input v-model="parentMsg"> <br> <child v-bind:my-message="parentMsg"></child> </div> ~~~ 你也可以使用 v-bind 的缩写语法: ~~~ <child :my-message="parentMsg"></child> ~~~ **`(重要)`**如果你想把一个`对象`的所有`属性`作为 prop 进行传递,可以使用不带任何参数的`v-bind`(即用 v-bind 而不是 v-bind:prop-name)。例如,已知一个`todo`对象: ~~~ todo: { text: 'Learn Vue', isComplete: false } ~~~ 然后: ~~~ <todo-item v-bind="todo"></todo-item> ~~~ 将等价于: ~~~ <todo-item v-bind:text="todo.text" v-bind:is-complete="todo.isComplete" ></todo-item> ~~~ ## Prop类型 目前为止,我们只看到字符串数组形式展示的 props: `props: ['title', 'likes', 'isPublished', 'commentIds', 'author']` 通常,你会希望每个 prop 都对应指定类型的值。在这些场景中,你可以将 props 展示为对象,其中每个属性的名称和值,分别包含 prop 名称和类型: ``` props: { title: String, likes: Number, isPublished: Boolean, commentIds: Array, author: Object } ``` ## Prop验证 为了指定 prop 验证,你需要将`props`的值定义为一个带有验证接收条件的对象,而不是一个由字符串构成的数组。例如: ``` Vue.component('my-component', { props: { // 基本类型(base type)的检查(`null` 表示接受所有类型) propA: Number, // 多种可能的类型 propB: [String, Number], // 必须传递,且 String 类型 propC: { type: String, required: true }, // Number 类型,有一个默认值 propD: { type: Number, default: 100 }, // Object 类型,有一个默认值 propE: { type: Object, // Object/Array 类型, // 默认必须返回一个工厂函数 default: function () { return { message: 'hello' } } }, // 自定义验证函数 propF: { validator: function (value) { // 值必须是这些字符串中的一个 return ['success', 'warning', 'danger'].indexOf(value) !== -1 } } } }) ``` 当 prop 验证失败,(如果使用的是开发构建版本,)Vue 就会在控制台抛出警告。 ![](https://box.kancloud.cn/9d83c9d2dc2986a452e0c4b34a8809a1_849x446.png)