+13

Một số mẹo với Vuejs

image.png

Thêm xóa với $set$delete

Một số phương pháp để có thể thêm và xóa các phần tử trong array và object

Array

add (newItem, index) {
  this.array.splice(index, 1, newItem)
}

// this.$set(array, indexOfItem, newValue)
add (newItem, index) {
  this.$set(this.array, index, newItem)
}

remove (index) {
 this.array.splice(index, 1)
}

// this.$delete(array, index)
remove (index) {
 this.$delete(this.todos, index)
}

Object

add (key, value) {
  this.object = { ...this.object, { key: value }}
}

// this.$set(object, propertyName, value)
add (key, value) {
  this.$set(this.object, key, value)
}

remove (key) {
  delete this.object[key]
} 

// this.$delete(object, propertyName)
remove (key) {
 this.$delete(this.object, key)
}

Cập nhật đồng bộ bằng $emit update

Cập nhật các prop của component cha một cách nhanh chóng từ component con

<dialog-component :visible.sync="isVisible" />
// DialogComponent
handleClose() {
  this.$emit('update:visible', false)
}

Được sử dụng cho các trường hợp đóng mở dialog nhanh chóng mà không cần truyền event lên component cha

Lưu ý khi dùng ở những chỗ khác cũng phải thêm .sync lúc truyền props để có thể sử dụng

Truy cập data của component cha bằng $parent

Phương pháp này giúp cho chúng ta có thể nhận được các data của component cha mà không cần truyền xuống prop

<p> {{ $parent.name }} </p>

Chỉ nên dùng khi component này không tái sử dụng

Xem console.log của event với $log

Tạo một vue prototype đặt tên là $log sau đó bind với console.log

Vue.prototype.$log = console.log.bind(console)

Và rồi chúng ta có thể sử dụng $log để kiểm tra console.log của các event trực tiếp trên template một cách nhanh chóng mà không cần tạo function

<input @keydown="$log" @keyup="$log" @keypress="$log" />

Rerender lại component với key

Phương pháp này được sử dụng đối với nhưng trường hợp component không tự render lại khi dư liệu thay đổi

Hoặc với trường hợp dưới đây là 2 path dùng chung một component với dữ liệu khác nhau, khi chúng ta thay đổi path thì component không rerender lại

const routes = [
  {
    path: "/path1",
    component: ViewComponent,
  },
  {
    path: "/path2",
    component: ViewComponent,
  },
];

Cách giải quyết là sử dụng key gán bằng $route.path, mỗi khi key là path thay đổi thì component sẽ rerender lại component

<component :key="$route.path" />

Tùy biến v-model

<input v-model="name" />
// v-model ở phiên bản đầy đủ sẽ là như thế này
<input :value="name" @input="name = $event.target.value" />

Nó có dạng

{ prop?: string, event?: string }

Với giá trị mặc định propvalue còn eventinput

Nếu chúng ta có thể không muốn dùng các event, prop mặc định, thì hãy thêm một property cho component tên model

export default {
  model: {
    prop: 'name'
    event: 'change',
  }
}

Khi dùng nó sẽ có dạng thế này

<input v-model="name" />
// v-model ở phiên bản đầy đủ sẽ là như thế này
<input :name="name" @change="name = $event.target.value" />

Sử dụng $on(‘hook:’)@hook

Khi component trở nên lớn dần thì cách viết này có thể giúp chúng ta quan sát các sự kiện dễ dàng hơn

export default {
  mounted() {
    window.addEventListener('resize', this.resizeHandler);
    this.$on("hook:beforeDestroy", () => {
      window.removeEventListener('resize', this.resizeHandler);
    })
  },
};

@hook có thể bắt được các lifecycle từ các component con

<child-comp @hook:mounted="someFunction" />

Dùng immediate để kích hoạt watch ngay khi khởi tạo

Nếu cần kích hoạt watch ngay khi component bắt đầu khởi tạo, sử dụng handler và set immediate bằng true

export default {
  watch: {
    title: {
      immediate: true,
      handler(newValue, oldValue) {
        console.log(newValue);
      },
    },
  },
};

Nhận tất các props và events với $props và $listeners

Khi chúng ta cần phải chỉnh sửa một thư viện hoặc một component nhiều tầng mà có nhiều props và sự kiện emit, chúng ta sẽ phải viết rất tốn công

<child-comp :placeholder="placeholder" :required="required" :value="value" @change="change" @click="click" />
export default {
  props: {
    placeholder: {
      type: String,
      default: '',
    },
    required: {
      type: Boolean,
      default: false,
    },
    value: {
      type: Number,
    },
  methods: {
    change(data){
      this.$emit('change', data);
    },
    click(data){
      this.$emit('click', data);
    }
  }
}

Thay vào đấy chúng ta có thể sử dụng cách bên dưới

<child-comp v-bind="$props" v-on="$listeners" />

Lưu ý là vẫn phải định nghĩa các props, còn các listeners sẽ tự động lắng nghe và emit ra ngoài

Khi chúng ta muốn thay thế một prop hoặc event

<child-comp v-bind="{ ...$props, value: 2 }" v-on="{ ...$listeners, click: handleClick }" />

Hoặc khi muốn bỏ một prop hoặc event

<child-comp v-bind="myProps" v-on="myListeners" />
export default {
  computed: {
    myListeners() {
      const { click, ...listeners } = this.$listeners;
      return listeners
    },
    myProps() {
      const { click, ...props } = this.$props;
      return props
    },
  },
}

Dynamic component, slot và event

Component

Một cách đơn giản và giảm thiếu số lượng code mà không cần phải dùng v-if v-else quá nhiều

<component :is="currentComponent" />
import ComponentA from './ComponentA.vue/';
import ComponentB from './ComponentB.vue/';

export default {
  data() {
    return {
      currentComponent: ComponentA,
    };
  },
  methods: {
    changeComponent(){
      this.currentComponent = ComponentB;
    }
  }
}

Nó sẽ rerender lại component mỗi khi currentComponent thay đổi Nếu muốn giữ nguyên dữ liệu khi chuyển component chúng ta có thể bọc keep-alive ở ngoài

<keep-alive>
    <component :is="currentComponent" />
</keep-alive>

Slot

Sử dụng khi muốn thay đổi slot mà không cần if else

<Component>
  <template v-slot:[dynamicSlotName]>
    ...
  </template>

  <template #[dynamicSlotName]>
    ...
  </template>
</Component>

Event

Sử dụng khi muốn thay đổi sự kiện theo điều kiện, ví dụ như muốn thay đổi sự kiện click sang dbclick thì đây là 1 cách hiệu quả

<button @[event]="test">Test</button>
export default {
  data() {
    return {
      event: 'click',
    };
  },
  methods: {
    changeEvent(){
      this.event = 'dbclick';
    }
  }
}

All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.