1. 组件使用的细节点 1
is 属性在 tbody 中应用
- <div id="root">
- <table>
- <tbody>
- <row></row>
- <row></row>
- <row></row>
- </tbody>
- </table>
- </div>
- <script>
- vue.component('row',{
- template:`<tr><td>this is a row</td></tr>`
- });
- var vm = new Vue({
- // el 限制一个 vue 实例的管理范围.
- el:"#root",
- });
- </script>
看似上面代码书写没有什么问题, 但是打开页面你会看到, 如下图:
所有的 tr 标签都跑到了 tbody 外面, 这是不符合规范的.
那么如何解决这个问题, 通过 is 属性, 只需要在原来代码改一下:
- <div id="root">
- <table>
- <tbody>
- <tr is="row"></tr>
- <tr is="row"></tr>
- <tr is="row"></tr>
- </tbody>
- </table>
- </div>
原有的 html 实例不变, 这样就可以避免 tr 标签上升到 tbody 标签外头了.
同样像 ul(li),select(option)
- <ul>
- <li is="row"></li>
- <li is="row"></li>
- <li is="row"></li>
- </ul>
- <select>
- <option is="row"></option>
- <option is="row"></option>
- <option is="row"></option>
- </select>
2. 组件使用的细节点 2
data 在子组件中, 必须为一个函数, 同时函数有返回数据.
- Vue.component('row',{
- data:function(){
- return {
- content:"this is content"
- }
- },
- template:`<tr><td>{{content}}</td></tr>`
- });
3. 在 Vue 中操作 DOM
Vue 不建议在代码中操作 DOM, 但是在复杂动画效果, 不操作 DOM, 光靠数据的绑定, 是无法实现的.
- <div id="app">
- <div ref="hw" @click="handleClick">hello world</div>
- </div>
- var App = new Vue({
- el:"#app",
- methods:{
- handleClick:function () {
- // 指的是 ref="hw" 的 DOM
- divDom = this.$refs.hw;
- console.log(divDom.innerHTML)
- }
- }
- })
那么在组件中是如何应用 ref, 咱们定义一个计数功能:
- <div id="root">
- <!-- 父组件监听 change 变化并交给 handleChange 处理 -->
- <counter @change="handleChange" ref="one"></counter>
- <counter @change="handleChange" ref="two"></counter>
- <div>{{total}}</div>
- </div>
- Vue.component("counter",{
- template:`<div @click="handleClick">{{number}}</div>`,
- data:function () {
- return {
- number:0
- }
- },
- methods:{
- handleClick:function () {
- this.number ++;
- // 子组件需要向父组件传递事件, 当当前组件数据发生变化时.
- this.$emit('change')
- }
- }
- });
- var vm = new Vue({
- // el 限制一个 vue 实例的管理范围.
- el:"#root",
- //total 用来计算两个 counter 组件内数据的和
- data:{
- total:0
- },
- methods:{
- handleChange:function () {
- //total 求和
- this.total = this.$refs.one.number + this.$refs.two.number
- }
- }
- });
4. 父子组件的数据传递
父组件可以向子组件传递参数, 但是子组件不能修改传递到子组件的参数, 这就是单向数据流.
方式 1: 子组件通过复制参数, 从而只更改复制过来的参数
- <div id="root">
- <!--1. 父组件向子组件传递名字为 count 的值 -->
- <counter :count="0"></counter>
- <counter :count="5"></counter>
- </div>
- var counter = {
- // 2. 子组件定义 props 接收 count
- data:function(){
- return {
- // 3. 既然子组件无法修改父组件传来的参数
- // 那么 number 为复制传过来的参数, 咱们使用 number
- number:this.count
- }
- },
- props:['count'],
- // 4. 子组件使用复制过来的 number,
- template:`<div @click="handleClick">{{number}}</div>`,
- methods:{
- handleClick:function () {
- // 并且还可以更改复制的 number
- this.number ++
- }
- }
- };
- var vm = new Vue({
- // el 限制一个 vue 实例的管理范围.
- el:"#root",
- components:{
- counter:counter
- }
- });
方式 2: 子组件向父组件传递事件
- <div id="root">
- <!--1. 父组件向子组件传递名字为 count 的值 -->
- <!-- 监听 inc 事件, 一旦触发执行父组件 handleIncrease 函数 -->
- <counter :count="0" @inc="handleIncrease"></counter>
- <counter :count="5" @inc="handleIncrease"></counter>
- <div>{{total}}</div>
- </div>
- var counter = {
- // 2. 子组件定义 props 接收 count
- data:function(){
- return {
- // 3. 既然子组件无法修改父组件传来的参数
- // 那么 number 为复制传过来的参数, 咱们使用 number
- number:this.count
- }
- },
- props:['count'],
- // 4. 子组件使用复制过来的 number,
- template:`<div @click="handleClick">{{number}}</div>`,
- methods:{
- handleClick:function () {
- // 并且还可以更改复制的 number
- this.number ++;
- // 5. 子组件通过触发事件, 将触发的 inc 事件传递给父组件
- this.$emit('inc',1)
- }
- }
- };
- var vm = new Vue({
- // el 限制一个 vue 实例的管理范围.
- el:"#root",
- data:{
- total:5,
- },
- components:{
- counter:counter
- },
- methods:{
- // 父组件定义函数
- handleIncrease:function (step) {
- // step 为子组件 $emit 的第二个参数.
- this.total += step
- }
- }
- });
5. 组件参数校验与非 props 特性
首先需要了解的是什么是 props 特性
props 特性其实就是, 在父组件中传入了参数, 恰巧子组件在 props 也定义了该参数的校验规则. 并且子组件能使用该参数在 template 进行渲染
- <child content="hell world"></child>
- Vue.component('child',{
- // 子组件接收 props
- props:{
- // 传入 content 的类型
- // 方式 1:content:[String,Number]
- // 方式 2:
- content:{
- type:String,// 要求传入值类型
- required:false,// 是否必填
- defaule:"default value",// 默认值
- validator:function (value) {
- // 传入数据长度大于 5
- return (value.length> 5)
- }
- }
- },
- template:`<div>Child</div>`
- });
- var vm = new Vue({
- el:"#root",
- });
非 props 特性
父组件向子组件传递的是一个属性, 子组件并没有声明该属性定义的内容.
1. 这样子组件就不能使用该属性在子组件 template 渲染.
2. 那么该属性会在 template 定义的最外层标签的标签里, 显示. e.g.: <div content="hello">hello</div>
6. 如何给组件绑定原生事件
当给一个组件标签绑定一个事件其实是自定义事件, 不会触发原生事件
- <div id="root">
- <!-- 当给一个组件标签绑定一个事件其实是自定义事件, 不会触发原生事件 -->
- <child @click="handleClick"></child>
- </div>
- Vue.component("child",{
- // 在标签绑定事件时原生的事件
- template:"<div @click='handleClick'>Child</div>",
- methods:{
- // 会触发
- handleClick:function () {
- alert("click click")
- }
- }
- });
- var vm = new Vue({
- el:"#root",
- methods:{
- // 不会触发
- handleClick:function () {
- alert("click")
- }
- }
- });
那么如何触发自定义事件?$emit
- Vue.component("child",{
- // 在标签绑定事件时原生的事件
- template:"<div @click='handleClick'>Child</div>",
- methods:{
- // 会触发
- handleClick:function () {
- // 通过 $emit 触发自定义事件
- this.$emit("click")
- }
- }
- });
但是这样写代码冗余, 过于繁琐? 通过添加事件修饰符. native
- <div id="root">
- <!-- 当给一个组件标签绑定一个事件其实是自定义事件, 不会触发原生事件 -->
- <!-- 通过添加. native 将该事件转为原生 click 事件 -->
- <child @click.native="handleClick"></child>
- </div>
- </body>
- <script>
- Vue.component("child",{
- // 在标签绑定事件时原生的事件
- template:"<div>Child</div>",
- });
- var vm = new Vue({
- el:"#root",
- methods:{
- // 不会触发
- handleClick:function () {
- alert("click")
- }
- }
- });
- </script>
持续更新中.....
来源: http://www.bubuko.com/infodetail-3392856.html