Vue2.0文档学习及案例总结之—-Components

释放双眼,带上耳机,听听看~!

Vue2.0文档学习及案例总结之—-Components

鉴于官方文档案例不够齐全,结合文档笔者总结了一下相对齐全的案例并均可运行出结果。可以更加深入具体地理解2.0文档的魅力,方便开发运用到实际项目中。


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="https://unpkg.com/vue/dist/vue.js"></script>
</head>
<body>
<h4>Using Compenents(使用组件)</h4>
<div id="example">
<my-component></my-component>
</div>
<script>
//        Vue.component('my-component', {
//            template: '<div>A custom component!</div>',
//        });
new Vue({
el: '#example',
components: {
myComponent: {
template: '<div>A custom component!</div>',
}
}
})
</script>
<h4>Local Registration(局域注册)! data在模板组件??</h4>
<div id="test"></div>
<div id="demo">
<parent></parent>
</div>
<script>
//        var Child = Vue.extend({
//            template: '<div>A local component!></div>'
//        });
//        var Parent = Vue.extend({//将子组件嵌套进父组件内
//            template: '<div>A Global component!<child></child></div>',
//            components: {
//                child: Child
//            }
//        });
new Vue({
el: '#demo',
data: {
msg: "hello"
},
components: {
'parent': {//将子组件嵌套进父组件内
template: '<div>A Global component!<child></child></div>',
components: {
child: {
template: '<div>A local component!</div>'
}
}
},
}
});
</script>
<h4>DOM Template Parsing Caveats</h4>
<div><p>一些 HTML 元素对什么元素可以放在它里面有限制。常见的限制:
a 不能包含其它的交互元素(如按钮,链接)
ul 和 ol 只能直接包含 li
select 只能包含 option 和 optgroup
table 只能直接包含 thead, tbody, tfoot, tr, caption, col, colgroup
tr 只能直接包含 th 和 td</p>
<p>另一个结果是,自定义标签(包括自定义元素和特殊标签)不能用在 ul, select, table 等对内部元素有限制的标签内。放在这些元素内部的自定义标签将被
提到元素的外面,因而渲染不正确。
</p>
<p>prefer using string templates whenever possible.
data Must Be a Function</p>
</div>
<h4>data MUST BE a Function</h4>
<div id="example-2">
<simple-counter></simple-counter>
<simple-counter></simple-counter>
<simple-counter></simple-counter>
</div>
<script>
//        data MUST BE a Function
Vue.component('simple-counter', {
template: '<button v-on:click="counter += 1">{{ counter }}</button>',
data: function () {
return {
counter: 0
}
}
});
new Vue({
el: '#example-2',
})
</script>
<h4>Composing Components 组件建构props down, events up</h4>
<p>Passing Data with Props(父到子)</p>
<hr>
<div id="demo2">
<child1 message="134a"></child1>
</div>
<script>
//组件实例的作用域是独立的
Vue.component('child1', {
props: {
message:{
type:String,
default:'13sd'
}
},//“信使RNA”,把值父到子单向传递过去
template: '<p>{{message}}</p>'
});
let demo2 = new Vue({
el: '#demo2'
})
</script>
<h4>camelCase vs.kebab-case</h4>
<div id="demo20">
<!--html里边kebab-case-->
<child1 my-message="hello 20!"></child1>
</div>
<script>
Vue.component('child1', {
props: ['my-message'],
template: '<p>{{myMessage }}</p>'
});
let demo20 = new Vue({
el: '#demo20'
})
</script>
<h4> Dynamic Props </h4>
<div id="demo21">
<!--子组件自定义message值传递不到父组件,只对自己有用-->
<child2 message="child 自定义的 message,只对自己用!"></child2>
<div>
<input v-model="message">
<br>
<child2 message="'message'+freeDom"></child2>
<child2 :message="':message'+message"></child2>
<child2 :message.once="':message.once'+message"></child2>
<child2 :message.sync="':message.sync'+message"></child2>
<!--直接引用引用父组件message-->
<child2 v-text="'v-text'+message"></child2>
</div>
</div>
<script>
Vue.component('child2', {
props: ['message'],//听父级传递数据
template: '<p>{{message}}</p>'
});
let demo21 = new Vue({
el: '#demo21',
data: {
message: 'parent message'
}
})
</script>
<h4>One-way Data Flow</h4>
<p>:msg(default),:msg.sync(double),:msg.once(once) 效果测试</p>
<p style="color:red">注意如果 prop 是一个对象或数组,是按引用传递。在子组件内修改它会影
响父组件的状态,不管是使用哪种绑定类型。</p>

<h4>Prop验证</h4>
<div id=”demo22″>
<demo22 v-text:prop-b=”‘aaa'”></demo22>
</div>
<script>
Vue.component(‘demo22’, {
template: ‘<div>{{propA}}</div>’,
props: {
// 基础类型检测 (null 意思是任何类型都可以)
propA: Number,
// 多种类型 (1.0.21+)
propM: [String, Number],
// 必需且是字符串
propB: {
type: String,
required: false
},
// 数字,有默认值
propC: {
type: Number,
default: 100
},
// 对象/数组的默认值应当由一个函数返回
propD: {
type: Object,
default: function () {
return {msg: ‘hello’}
}
},
// 指定这个 prop 为双向绑定
// 如果绑定类型不对将抛出一条警告
propE: {
twoWay: true
},
// 自定义验证函数
propF: {
validator: function (value) {
return value > 10
}
},
// 转换函数(1.0.12 新增)
// 在设置值之前转换值
propG: {
coerce: function (val) {
return val + ” // 将值转换为字符串
}
},
propH: {
coerce: function (val) {
return JSON.parse(val) // 将 JSON 字符串转换为对象
}
}
}
});
// create a root instance(构建根实例)
new Vue({
el: ‘#demo22’,
})
</script>
<h4>Custom Events–定制事件,子向父通信</h4>
<div id=”counter-event-example”>
<p>每个 Vue 实例都是一个事件触发器:
使用 $on() 监听事件;
使用 $emit() 在它上面触发事件;
使用 $dispatch() 派发事件,事件沿着父链冒泡;
使用 $broadcast() 广播事件,事件向下传导给所有的后代。</p>
<p>{{ total }}</p>
<button-counter v-on:increment=”incrementTotal”></button-counter>
<button-counter v-on:increment=”incrementTotal”></button-counter>
<hr>
<p>Binding Native Events to Components</p>
<button-counter v-on:click.native=”test”></button-counter>
</div>
<script>
Vue.component(‘button-counter’, {
template: ‘<button v-on:click=”increment”>{{ counter }}</button>’,
data: function () {
return {
counter: 0
}
},
methods: {
increment: function () {
this.counter += 1;
this.$emit(‘increment’)
},

    }
});
let aa = new Vue({
    el: '#counter-event-example',
    data: {
        total: 0
    },
    methods: {
        incrementTotal: function () {
            this.total += 1
        },
        test: function () {
            alert('test');
        }
    }
})

</script>
<h4>Form Input Components using Custom Events</h4>
<p>This interface can be used not only to connect with form inputs inside a component, but also to easily integrate
input types that you invent yourself. Imagine these possibilities:</p>
<div id=”v-model-example”>
<p>{{ message }}</p>
<my-input
label=”Message”
v-model=”message”

</my-input>
</div>
<script>
Vue.component(‘my-input’, {
template: ‘/
<div class=”form-group”>/
<label v-bind:for=”randomId”>{{ label }}:</label>/
<input v-bind:id=”randomId” v-bind:value=”value” v-on:input=”onInput”>/
</div>/
‘,
props: [‘value’, ‘label’],
data: function () {
return {
randomId: ‘input-‘ + Math.random()
}
},
methods: {
onInput: function (event) {
this.$emit(‘input’, event.target.value)
}
},
})
new Vue({
el: ‘#v-model-example’,
data: {
message: ‘hello’
}
})
</script>
<p>父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译</p>
<h4>Non Parent-Child Communication</h4>
<div class=”bus”>
<display></display>
<increment></increment>
</div>
<script>
var bus = new Vue();
Vue.component(‘increment’, {
template: <button @click="increment">increment</button>,
data: function () {
return ({count: 0})
},
methods: {
increment: function () {
var increment = ++this.count;
//触发该组件中的事件
bus.$emit(‘inc’, increment)
}
}
});
Vue.component(‘display’, {
template: <span>Clicked: {{count}} times</span>,
data: function () {
return {count: 0}
},
created: function () {
//在该组件中创建钩子监听事件
bus.$on(‘inc’, function (num) {
this.count = num
}.bind(this));
}
});
vm = new Vue({
el: “.bus”,
})
</script>
<h4>Content Distribution with Slots(内容分发)</h4>
<div id=”appa”>
<my-component>
<h1>Hello Vue.js!</h1>
</my-component>

<my-component>
</my-component>

</div>
<template id=”myComponent”>
<div>
<h2>slot 其实只是个替补</h2>
<slot>如果没有分发内容,则显示我slot中的内容</slot>
<h3>无则上位</h3>
</div>
</template>
<script>
Vue.component(‘my-component’, {
template: ‘#myComponent’
});

new Vue({
    el: '#appa'
})

</script>
<hr>
<div id=”appb”>
<button class=”btn btn-open” @click=”openDialog”>dialog</button>
<modal-dialog v-show.sync=”show”>
<header class=”dialog-header” slot=”header”>
<h1 class=”dialog-title”>header</h1>
</header>
<main class=”dialog-body” slot=”body”>
<h3>main</h3>
</main>
<footer class=”dialog-footer” slot=”footer”>
<button @click=”closeDialog”>footer关闭</button>
</footer>
</modal-dialog>
</div>
<template id=”dialog-template”>
<div><!–让谁显示谁显示–>
<slot name=”header”></slot>
<slot name=”body”></slot>
<slot name=”footer”></slot>
</div>
</template>
<script>
Vue.component(‘modal-dialog’, {
template: ‘#dialog-template’,
props: [‘show’],
methods: {
close: function () {
this.show = false
}
}
});
new Vue({
el: ‘#appb’,
data: {
show: false
},
methods: {
openDialog: function () {
this.show = true
},
closeDialog: function () {
this.show = false
}
}
})
</script>
<hr>
<div id=”app”>
<script type=”text/x-template” id=”modal-template”>
<transition name=”modal”>
<div class=”modal-mask”>
<div class=”modal-wrapper”>
<div class=”modal-container”>

                    <div class="modal-header">
                        <slot name="header">
                            default header
                        </slot>
                    </div>

                    <div class="modal-body">
                        <slot name="body">
                            default body
                        </slot>
                    </div>

                    <div class="modal-footer">
                        <slot name="footer">
                            default footer
                            <button class="modal-default-button" @click="$emit('close')">
                                OK
                            </button>
                        </slot>
                    </div>
                </div>
            </div>
        </div>
    </transition>
</script>
<button id="show-modal" @click="showModal = true">Show Modal</button>
<modal v-if="showModal" @close="showModal = false">
    <h3 slot="header">custom header</h3>
</modal>

</div>
<script>
Vue.component(‘modal’, {
template: ‘#modal-template’
});
new Vue({
el: ‘#app’,
data: {
showModal: true
}
})
</script>
<hr>
<h4>Dynamic Components</h4>
<div id=”app1″>
<p>如果把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染</p>
<keep-alive>
<!–<component :is=”currentView”></component>–>
<!–<home :is=”currentView”></home>–>
<home :is=”currentView1″></home>
<!–<home :is=”currentView2″></home>–>
<!–<home :is=”currentView3″></home>–>
</keep-alive>
<hr>
<home></home>
<home :is=”currentView”></home>
<posts :is=”currentView1″></posts>
<posts :is=”currentView2″></posts>
</div>
<script>
var choose2 = {
template: ‘<p>Welcome home!</p>’
};//组件可以是全局的也可以是局部的
new Vue({
el: ‘#app1’,
data: {
currentView: ‘home’,
currentView1: ‘posts’,
currentView2: choose2,
currentView3: ‘archive’
},
components: {
home: {
template: ‘<main>home</main>’
},
posts: {
template: ‘<div>posts</div>’
},
archive: {
template: ‘<h1>archive</h1>’
}
}
})

</script>
<h4>Misc 杂项</h4>
<hr>
<h4>Authoring Reusable Components:编写可复用组件</h4>
<p>在编写组件时,记住是否要复用组件有好处。一次性组件跟其它组件紧密耦合没关系,
但是可复用组件应当定义一个清晰的公开接口。</p>
<p>
Vue.js 组件 API 来自三部分——prop,事件和 slot:
prop 允许外部环境传递数据给组件;
事件 允许组件触发外部环境的 action;
slot 允许外部环境插入内容到组件的视图结构内。
</p>
<div id=”misc1″>
<p>使用 v-bind 和 v-on 的简写语法,模板的缩进清楚且简洁</p>
<!–<my-component–>
<!–:foo=”baz”–>
<!–:bar=”qux”–>
!–@event-a=”doThis”–
!–@event-b=”doThat”–>
<!–<!– content –>–>
<!–<img slot=”icon” class=”lazyload” src=”data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC” data-original=”…”>–>
<!–<p slot=”main-text”>Hello!</p>–>
<!–</my-component>–>
<p>Async Components:异步组件</p>
<p>在大型应用中,我们可能需要将应用拆分为小块,只在需要时才从服务器下载。为了让事情更简单,Vue.js 允许将组件定义为一个工厂函数,动态地解析组件的定义。Vue.js 只在组件需要渲染时触发工厂函数,
并且把结果缓存起来,用于后面的再次渲染。</p>
<script>
Vue.component(‘async-example’, function (resolve, reject) {
setTimeout(function () {
resolve({
template: ‘<div>I am async!</div>’
})
}, 1000)
});
Vue.component(‘async-webpack-example’, function (resolve) {
// 这个特殊的 require 语法告诉 webpack
// 自动将编译后的代码分割成不同的块,
// 这些块将通过 ajax 请求自动下载。
// Webpack’s code-splitting(代码分隔) feature:
require([‘./my-async-component’], resolve)
});
// You can also return a Promise in the resolve function, so with
// Webpack 2 + ES2015 syntax you can do:
// Vue.component(
// ‘async-webpack-example’,
// () => System.import(‘./my-async-component’)
// );
// If you’re a Browserify user that would like to use async components,
// it’s unfortunately not possible and probably never will be, as its creator has made it clear that async loading “is not something that Browserify will ever support.” If this is a feature
// that’s important to you, we recommend using Webpack instead.
</script>
<p>Component Naming Conventions</p>
<script>
// When registering components (or props), you can use kebab-case,
// camelCase, or TitleCase. Vue doesn’t care.
// in a component definition
// components: {
// ‘kebab-cased-component’: { // },
// ‘camelCasedComponent’: { // },
// ‘TitleCasedComponent’: { // }
// }
</script>
<div>
<!– alway use kebab-case in HTML templates –>
<!– When using string templates however, <my-component/>也行
we’re not bound by HTML’s case-insensitive restrictions. –>
<kebab-cased-component></kebab-cased-component>
<camel-cased-component></camel-cased-component>
<title-cased-component></title-cased-component>
</div>
</div>
<h4>Recursive(递归) Components</h4>
<div id=”misc2″>
<!–<stack-overflow></stack-overflow>–>
<!–<script>–>
<!–Vue.component(‘stack-overflow’, {–>
<!–name: ‘stack-overflow’,–>
<!–template: --> <!--<div>--> <!--<stack-overflow v-if="false">hello</stack-overflow>--> <!--</div>--> <!--–>
<!–});–>
<!–//vue.js:2224 Uncaught RangeError: Maximum call stack size exceeded(…)–>
<!–new Vue({–>
<!–el: ‘#misc2’,–>
<!–})–>
<!–</script>–>
</div>
<h6>Inline Templates</h6>
<p>如果子组件有 inline-template 特性,组件将把它的内容当作它的模板,而不是把它当作分发内容。这让模板更灵活。</p>
<p>但是 inline-template 让模板的作用域难以理解。</p>
<div class=”inline”>
<my-component inline-template>
<div>
<p>These are compiled as the component’s own template.</p>
<p>Not parent’s transclusion content.</p>
<mark> 这些被编译为组件自己的模板,而非父组件的过渡内容</mark>
</div>
</my-component>
</div>
<script>

</script>
<h4 style=”color:red”>X-Templates</h4>
<mark>这在有很多模版或者小的应用中有用,否则应该避免使用,因为它将模版和组件的其他定义隔离了。</mark>
<div id=”misc3″>
<script type=”text/x-template” id=”modal-template-a” name=”modal-a”>
<div>hello x-template</div>
</script>
<!– use the modal component–>
<modal-a></modal-a>
</div>
<script>
Vue.component(‘modal-a’, {
template: ‘#modal-template-a’
});
// start app
new Vue({
el: ‘#misc3’,
})
</script>
<h4>Cheap Static Components with v-once:一次性组件</h4>
<mark>当组件中包含大量静态内容时,可以考虑使用 v-once 将渲染结果缓存起来</mark>
<div id=”misc4″>
<p>Rendering plain HTML elements is very fast in Vue, but sometimes
you might have a component that contains a lot of static content.
In these cases, you can ensure that it’s only evaluated once(只评估一次) and then cached by
adding the v-once directive to the root element, like this:</p>
<hr>
<terms-of-service></terms-of-service>
</div>
<script>
var aas = Vue.component(‘terms-of-service’, {
template: <div v-once> <h3>Terms of Service---'v-once'</h3> <mark>I am a cheap component which is rendered only once</mark> </div>

});
new Vue({
    el: '#misc4',
    components: {
        termsOfService: "aas"
    }
})

</script>
</body>
</html>

【转自慕课】https://www.imooc.com

Vue.js

分享一个精致完整的Vue2+项目[douban]供大家交流学习

2022-3-3 19:46:54

Vue.js

uni-app、Vue3 + ucharts 图表 H5 无法渲染

2022-3-3 19:47:11

搜索